描述符类(property)
含义:将某种特殊类型的类的实例指派给另一个类的属性
特殊类型:
至少实现以下三种方法中的一个
- def __init__(self, default):
用于访问属性,返回属性的数值
- def __get__(self, instance, owner):
将在属性分配操作中调用,不返回任何内容
- def __set__(self, instance, value):
控制删除操作,不返回任何内容
Eg1:自定义MyDecirptor类,定义一个Test类,x值为MyDecirptor的实例化对象
class MyDecirptor():
def __get__(self, instance, owner):
print("__get__",self, instance, owner)
def __set__(self, instance, value):
print("__set__",self, instance, value)
def __delete__(self, instance):
print("__delete__",self, instance)
class Test:
x = MyDecirptor()
t = Test()
print(t.x) # 实行get函数,self:MyDecirptor类,instance:实例对象t,owner:t的类对象Test
print(t) # Test实例化,MyDecirptor实例化,无返回值
t.x = "123" # 实行set函数
del t.x # 实行delete函数
实行结果:
__get__ <__main__.MyDecirptor object at 0x0000000002226B00> <__main__.Test object at 0x0000000002226D30> <class '__main__.Test'>
None
__set__ <__main__.MyDecirptor object at 0x0000000002226B00> <__main__.Test object at 0x0000000002226D30> 123
__delete__ <__main__.MyDecirptor object at 0x0000000002226B00> <__main__.Test object at 0x0000000002226D30>
EG2:自定义MyDecirptor类,定义一个Test类定义了get,set,del函数,x值为MyDecirptor的实例化对象,通过触发MyDecirptor函数进行回调Test类中的get,set,del函数
class MyProperty():
def __init__(self, fget=None, fset=None, fdel=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __get__(self, instance, owner):
return self.fget(instance)
def __set__(self, instance, value):
self.fset(instance, value)
def __delete__(self, instance): # 必须是delete,不能是del
self.fdel(instance)
class C():
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX) # 属性x有个描述符类的方法
c = C()
c.x = "super man"
print(c.x)
del c.x
实行结果:
super man
解析:
c = C()实行时,调用C对象的构造函数__init__方法。
c.x = "super man" 调用时,先调用MyProperty的__set__方法通过__set__方法调用C的setX方法完成设置 。
同理:print(c.x)调用MyProperty的__get__方法
del c.x调用MyProperty的__del__方法
注意:MyProperty和Property的代码一样
定制容器:
协议(protocols):规定了你哪些方法必须要定义,python中,协议更像是一个指南(建议)
如果希望定制的容器不可变,只需要定义__len__()和__getitem__()方法
如果希望定制的容器是可变的,需要定义__len__(),_getitem__(),__setitem__(),__delitem__四个方法。