一、内置attr:__setattr__,__delattr__,__getattr__
- __setattr__ #添加/修改属性会触发它的执行
- __delattr__ #删除属性的时候会触发
- __getattr__ #只有在调用属性且属性不存在的时候才会触发
class Foo: def __init__(self,x): self.name=x def __setattr__(self, key, value): # if not isinstance(value,str): # raise TypeError('must be str') # print('----setattr---key:%s,value:%s' %(key,value)) # print(type(key)) # print(type(value)) # self.key=value # setattr(self,key_str,value) #self.key_attribute=value #这是无限递归 self.__dict__[key]=value #因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值 def __delattr__(self, item): print('delattr:%s' %item) print(type(item)) # delattr(self,item) #这是无限递归 # del self.item self.__dict__.pop(item) #我们可以直接修改属性字典,来完成添加/修改属性的操作 f1=Foo('egon') #f1.name='egon' f1.age=18 print(f1.__dict__) print(f1.name) print(f1.age) print(f1.__dict__) del f1.age print(f1.__dict__) print(f1.age) #---------------------getattr------------------------ class Foo: def __init__(self,x): self.name=x #属性不存在的情况下才会触发 def __getattr__(self, item): print('getattr-->%s %s' %(item,type(item))) f=Foo('egon') # print(f.name) print(f.xxxxxxx)
二、二次加工标准类型(包装)
包装:python默认提供了标准数据类型,以及丰富的内置方法,有时候需要基于标准数据类型来定制我们自己的数据类型,新增或改写方法,这就用到了继承和派生知识(标准类型均可以通过以下方式进行二次加工)
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
实现授权的关键点就是覆盖__getattr__方法
定制自己的数据类型:
- 继承的方式
- 授权的方式
l=list([1,2,3]) l.append(4) l.append('5') print(l) class List(list): pass l1=List([1,2,3]) print(l1) l1.append(4) print(l1) l1.append('5') print(l1)
#基于继承的原理,来定制自己的数据类型(继承标准类型) class List(list): def append(self, p_object): # print('--->',p_object) if not isinstance(p_object,int): raise TypeError('must be int') # self.append(p_object) super().append(p_object) def insert(self, index, p_object): if not isinstance(p_object,int): raise TypeError('must be int') # self.append(p_object) super().insert(index,p_object) # l=List([1,2,3]) # print(l) # l.append(4) # print(l) # l.append('5') print(l) # l.insert(0,-1) l.insert(0,'-1123123213') print(l) # def test(x:int,y:int)->int: # return x+y # print(test.__annotations__) # # print(test(1,2)) # print(test(1,'3')) # # def test(x,y): # return x+y
#不能用继承,来实现open函数的功能 # f=open('a.txt','w') # print(f) # f.write('1111111') #授权的方式实现定制自己的数据类型 import time class Open: def __init__(self,filepath,m='r',encode='utf-8'): self.x=open(filepath,mode=m,encoding=encode) self.filepath=filepath self.mode=m self.encoding=encode def write(self,line): print('f自己的write',line) t=time.strftime('%Y-%m-%d %X') self.x.write('%s %s' %(t,line)) def __getattr__(self, item): # print('=------>',item,type(item)) return getattr(self.x,item) # # f=Open('b.txt','w') # # print(f) # f.write('111111 ') # f.write('111111 ') # f.write('111111 ') f=Open('b.txt','r+') # print(f.write) print(f.read) res=f.read() #self.x.read() print(res) print('=-=====>',f.read()) f.seek(0) print(f.read()) # f.flush() # f.close()