上下文管理协议和元类
上下文管理协议和元类
item系列:
把对象操作属性模拟成字典的格式。
#把对象操作属性模拟成字典的格式 class Foo: def __init__(self,name): self.name=name def __setattr__(self, key, value): print('setattr===>') def __getitem__(self, item): # print('getitem',item) return self.__dict__[item] def __setitem__(self, key, value): print('setitem-----<') self.__dict__[key]=value def __delitem__(self, key): self.__dict__.pop(key) # self.__dict__.pop(key) # def __delattr__(self, item): # print('del obj.key时,我执行') # self.__dict__.pop(item) f=Foo('George') f.name='Wang' f['name']='George' # print(f.name) # f.name='George' # f['age']=18 # print(f.__dict__) # # del f['age'] #del f.age # print(f.__dict__) # print(f['name'])
__slots__方法:对象不会去建立新的名称空间,这样可以节省内存。但是它会限制使用属性,所以它的使用场景是一个类要产出多个固定的属性的时候,这时就可以用__slots__来统一管理了。
class People: x=1 def __init__(self,name): self.name=name def run(self): pass print(People.__dict__) #查看People的属性 p=People('alex') print(p.__dict__) class People: __slots__=['x','y','z'] p=People() print(People.__dict__) p.x=1 p.y=2 p.z=3 print(p.x,p.y,p.z) # print(p.__dict__) p1=People() p1.x=10 p1.y=20 p1.z=30 print(p1.x,p1.y,p1.z) print(p1.__dict__)
实现迭代器协议
from collections import Iterable,Iterator class Foo: def __init__(self,start): self.start=start def __iter__(self): return self def __next__(self): return 'aSB' f=Foo(0) # f.__iter__() #有__iter__就是可迭代的 # f.__next__() #有__next__就是迭代器 print(isinstance(f,Iterable)) print(isinstance(f,Iterator)) print(next(f)) #f.__next__() print(next(f)) #f.__next__() print(next(f)) #f.__next__() for i in f: #先执行__iter__方法,变成迭代器,然后就可以__next__, res=f.__iter__() #__iter__得到的就是自己self #next(res) print(i)
例如:
######有一个初始值,每次自加一 from collections import Iterable,Iterator class Foo: def __init__(self,start): self.start=start def __iter__(self): return self def __next__(self): if self.start > 10: raise StopIteration n=self.start self.start+=1 return n f=Foo(0) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) # print(next(f)) for i in f: print('====>',i)
模拟range:
class Range: '123' def __init__(self,start,end): self.start=start self.end=end def __iter__(self): return self def __next__(self): if self.start == self.end: raise StopIteration n=self.start self.start+=1 return n for i in Range(0,3): print(i) print(Range.__doc__)
析构函数: __del__,在__del__中定义一些清理操作。比如关闭。
import time class Open: def __init__(self,filepath,mode='r',encode='utf-8'): self.f=open(filepath,mode=mode,encoding=encode) def write(self): pass def __getattr__(self, item): return getattr(self.f,item) def __del__(self): print('----->del') self.f.close() f=Open('a.txt','w') f1=f #f1=f时,先执行print("=====>")的操作,在去执行def f del f print('=========>')
上下文管理协议
# with open('a.txt','r') as f: # print('--=---->') # print(f.read()) # with open('a.txt', 'r'): # print('--=---->') class Foo: def __enter__(self): print('=======================》enter') return 111111111111111 def __exit__(self, exc_type, exc_val, exc_tb): print('exit') print('exc_type',exc_type) print('exc_val',exc_val) print('exc_tb',exc_tb) return True # with Foo(): #res=Foo().__enter__() # pass with Foo() as obj: #res=Foo().__enter__() #obj=res #with Foo() as obj是将with Foo()的结果给obj。 print('with foo的自代码块',obj) raise NameError('名字没有定义') print('************************************') print('1111111111111111111111111111111111111111')
实现上下文管理协议
class Open: def __init__(self,filepath,mode,encode='utf-8'): self.f=open(filepath,mode=mode,encoding=encode) self.filepath=filepath self.mode=mode self.encoding=encode def write(self,line): print('write') self.f.write(line) def __getattr__(self, item): return getattr(self.f,item) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() return True with Open('aaaaa.txt','w') as write_file: #write_file=Open('aaaaa.txt','w') write_file.write('123123123123123\n') write_file.write('123123123123123\n') #print(sssssssssssssss) write_file.write('123123123444123123\n')
call方法:
对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象=类名();而对于__call__方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class People: def __init__(self,name): self.name=name def __call__(self, *args, **kwargs): print('call') p=People('George') print(callable(People)) print(callable(p)) p() #加call方法会直接触发call方法的运行,打印call
元类:元类是类的类,是类的模板。
元类是用来控制如何创建类的,正如类是创建对象的模板一样。
# class People: # def __init__(self,name): # self.name=name # # p=People('egon') # print(type(p)) # print(type(People)) #####typer产生类,类产生对象。 # class Foo: # x=1 # def run(self): # pass # print(type(Foo)) #####type成为元类,是所有类的类,利用type模拟class关键字的创建类的过程 def run(self): print('%s is runing' %self.name) class_name='Bar' #类的名字 bases=(object,) #类的继承关系 class_dic={ #类的属性字典 'x':1, 'run':run } print(class_dic) Bar=type(class_name,bases,class_dic) print("Bar",Bar) print(type(Bar))
自定制元类:
class Mymeta(type): #Mymeta继承type这个元类 def __init__(self,class_name,class_bases,class_dic): # print(self) # print(class_name) # print(class_bases) # print(class_dic) for key in class_dic: if not callable(class_dic[key]):continue if not class_dic[key].__doc__: raise TypeError('小子,你没写注释,赶紧去写') # type.__init__(self,class_name,class_bases,class_dic) class Foo(metaclass=Mymeta): #metaclass=Mymeta是指定元类 x=1 def run(self): 'run function' print('running') # Foo=Mymeta('Foo',(object,),{'x':1,'run':run}) #实例化 print(Foo.__dict__) class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): pass def __call__(self, *args, **kwargs): print(self) obj=self.__new__(self) self.__init__(obj,*args,**kwargs) #obj.name='egon' return obj class Foo(metaclass=Mymeta): x=1 def __init__(self,name): self.name=name #obj.name='egon' def run(self): 'run function' print('running') print(Foo.__dict__) f=Foo('egon') print(f) print(f.name)
------- END -------