面向对象的迭代器协议
class Foo: def __init__(self,n): self.n = n def __iter__(self): return self def __next__(self): if self.n == 13: raise StopIteration("终止了") self.n += 1 return self.n f1 = Foo(10) # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) # print(f1.__next__()) for i in f1: #obj=iter(f1) ------> f1.__iter__() for循环会自动捕捉到终止条件 print(i) #obj.__next__()
1 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
2 描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
3 描述符分两种
一 数据描述符:至少实现了__get__()和__set__()
二 非数据描述符:没有实现__set__()
4 注意事项:
一 描述符本身应该定义成新式类,被代理的类也应该是新式类
二 必须把描述符定义成另一个类的类属性,不能为定义到构造函数中
三 要严格遵循该优先级,优先级由高到底分别是
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.找不到的属性触发__getattr__()
class Foo: #描述符 def __get__(self, instance, owner): print("__get__") def __set__(self, instance, value): print("__set__") def __delete__(self, instance): print("__delete__") class Bar: x = Foo() #描述了x属性 def __init__(self,n): self.x = n #触发描述符 b1 = Bar(10) #触发描述符的set方法 print(b1.__dict__) #空字典 print(Bar.__dict__) b1.x #触发描述符的get方法 del b1.x #触发描述符的delete方法
描述符的应用
#描述符 class Type: def __get__(self, instance, owner): #instance是被描述的类的实例,就是p1 print("__get__方法") print("instance参数[ %s ]"%instance) print("owner参数[ %s ]" % owner) def __set__(self, instance, value): print("__set__方法") print("instance参数[ %s ]" % instance) print("value参数[ %s ]" % value) def __delete__(self, instance): print("__delete__方法") print("instance参数[ %s ]" % instance) class People: name = Type() #描述了name 属性 def __init__(self,name,age): self.name = name self.age = age p1 = People("tom",18) #执行描述符的set方法 print("---->>>>>",p1) p1.name #执行描述符的get方法 p1.name = "liaoboshi" #执行描述符的set方法 print(p1.__dict__) #没有name这个属性,因为描述符的方法没有返回值
描述符的应用
#描述符 class Type: def __init__(self,key,expected_type): self.key = key self.expected_type = expected_type def __get__(self, instance, owner): #instance是被描述的类的实例,就是p1 print("__get__方法") return instance.__dict__[self.key] def __set__(self, instance, value): print("__set__方法") if not isinstance(value,self.expected_type): #检测传进来的类型 raise TypeError(" %s 你传入的类型不是 %s"%(self.key,self.expected_type)) instance.__dict__[self.key] = value def __delete__(self, instance): print("__delete__方法") instance.__dict__.pop(self.key) class People: name = Type("name",str) #描述了name 属性(描述符要传2个参数) age = Type("age",int) #描述了age 属性(描述符要传2个参数) def __init__(self,name,age): self.name = name self.age = age p1 = People("tom",18) # p2 = People(213,18) #报错,name传入的类型必须是字符串型
类的装饰器
def deco(obj): print("========>",obj) #obj就是Foo类本身 obj.x = 1111111 obj.y = 2222222 return obj @deco # Foo=deco(Foo) class Foo: pass print(Foo.__dict__) #属性字典里有x 和 y 属性
类的装饰器
def Typed(**kwargs): def deco(obj): for key,val in kwargs.items(): setattr(obj,key,val) return obj return deco @Typed(x=1,y=2,z=3) #@Typed(x=1,y=2,z=3) --->@deco ---> Foo=deco(Foo) class Foo: pass print(Foo.__dict__) @Typed(name="tom") #@Typed(name="tom") --->@deco ---> Foo=deco(Foo) class Bar: print() print(Bar.name)
类的装饰器的应用
#描述符 class Type: def __init__(self,key,expected_type): self.key = key self.expected_type = expected_type def __get__(self, instance, owner): #instance是被描述的类的实例,就是p1 print("__get__方法") return instance.__dict__[self.key] def __set__(self, instance, value): print("__set__方法") if not isinstance(value,self.expected_type): #检测传进来的类型 raise TypeError(" %s 你传入的类型不是 %s"%(self.key,self.expected_type)) instance.__dict__[self.key] = value def __delete__(self, instance): print("__delete__方法") instance.__dict__.pop(self.key) def deco(**kwargs): #kwargs={"name":str,"age":int} def wrapper(obj): #obj=People for key,val in kwargs.items(): #(("name",str),("age",int)) setattr(obj,key,Type(key,val)) #setattr(People,"name",Type("name",str)) return obj return wrapper @deco(name=str,age=int) #@deco(name=str,age=int) ===> @wrapper ===>People=wrapper(People) class People: def __init__(self,name,age): self.name = name self.age = age p1 = People("tom",18)
利用描述符自定制property
class Lazyproperty: def __init__(self,funy): #funy ==>area print("=====>",funy) self.funy = funy def __get__(self, instance, owner): if instance is None: return self res = self.funy(instance) return res class Room: def __init__(self,name,width,length): self.name = name self.width = width self.length = length # @property @Lazyproperty # area= Lazyproperty(area) def area(self): return self.width * self.length r1 = Room("厕所",1,1) print(r1.area) print(r1.__dict__) class Lazyproperty: def __init__(self,funy): #funy ==>area print("=====>",funy) self.funy = funy def __get__(self, instance, owner): if instance is None: return self res = self.funy(instance) setattr(instance,self.funy.__name__,res) #把返回值加到属性字典里 return res class Room: def __init__(self,name,width,length): self.name = name self.width = width self.length = length # @property @Lazyproperty # area= Lazyproperty(area) def area(self): return self.width * self.length r1 = Room("厕所",1,1) print(r1.area) print(r1.__dict__)
上下文管理协议
class Open: def __init__(self,name): self.name = name def __enter__(self): print("执行了__enter__") return self def __exit__(self, exc_type, exc_val, exc_tb): print("执行了__exit__") with Open("a.txt") as f: #执行这一行的时候,会自动调用__enter__方法 print(f) # f 就是Open类产生的对象 print(f.name) #with as 里面的代码执行完的时候,会自动调用__exit__方法 print("------------------>>>>>>>>") class Open: def __init__(self,name): self.name = name def __enter__(self): print("执行了__enter__") return self def __exit__(self, exc_type, exc_val, exc_tb): print("执行了__exit__") print(exc_type) #没有异常输出None,有就输出异常的类型 print(exc_val) #没有异常输出None,有就输出异常的值 print(exc_tb) #没有异常输出None,有就输出traceback return True #返回True,吞掉异常 with Open("a.txt") as f: #执行这一行的时候,会自动调用__enter__方法 print(f) # f 就是Open类产生的对象 print(dsafsfsf) #异常的情况下,会执行__exit__,如果返回True,会吞掉异常,执行with as 外面的代码, # 如果返回不是Ture,吐出异常,不会执行with as 外面的代码,报错 print(f.name) #with as 里面的代码执行完的时候,会自动调用__exit__方法 print("------------------>>>>>>>>")
metaclass
1 class Foo: 2 pass 3 4 f1=Foo() #f1是通过Foo类实例化的对象
python中一切皆是对象,类本身也是一个对象,当使用关键字class的时候,python解释器在加载class的时候就会创建一个对象(这里的对象指的是类而非类的实例)
上例可以看出f1是由Foo这个类产生的对象,而Foo本身也是对象,那它又是由哪个类产生的呢?
1 #type函数可以查看类型,也可以用来查看对象的类,二者是一样的 2 print(type(f1)) # 输出:<class '__main__.Foo'> 表示,obj 对象由Foo类创建 3 print(type(Foo)) # 输出:<type 'type'>
2 什么是元类?
元类是类的类,是类的模板
元类是用来控制如何创建类的,正如类是创建对象的模板一样
元类的实例为类,正如类的实例为对象(f1对象是Foo类的一个实例,Foo类是 type 类的一个实例)
type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类其实都是type类实例化的对象
3 创建类的两种方式
方式一:
1 class Foo: 2 def func(self): 3 print('from func')
方式二:
1 def func(self): 2 print('from func') 3 x=1 4 Foo=type('Foo',(object,),{'func':func,'x':1})
4 一个类没有声明自己的元类,默认他的元类就是type,除了使用元类type,用户也可以通过继承type来自定义元类(顺便我们也可以瞅一瞅元类如何控制类的创建,工作流程是什么)
class Mytype(type): def __init__(self,what,bases=None,dict=None): print(what,bases,dict) def __call__(self, *args, **kwargs): print('--->') obj=object.__new__(self) self.__init__(obj,*args,**kwargs) return obj class Room(metaclass=Mytype): def __init__(self,name): self.name=name r1=Room('alex') print(r1.__dict__) 自定制元类精简版