python 面向对象2
面向对象的迭代器协议
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__)
自定制元类精简版
浙公网安备 33010602011771号