Python描述符以及Property方法的实现原理
Python描述符以及Property方法的实现原理
描述符的定义:
描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议
__get__():调用一个属性时,触发
__set__():为一个属性赋值时,触发
__delete__():采用del删除属性时,触发
描述符作用:
描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中)
可以说成是属性的属性,定义属性的属性
描述符本身的实例并不会触发这三个方法
class dis:
def __set__(self, instance, value):
print('正在执行__set__方法.....')
def __delete__(self, instance):
print('正在执行__delete__方法')
def __get__(self, instance, owner):
print('正在执行__get__方法')
d = dis()
d.name = "1"
print(d.name)
del d.name
#================输出===================
1
描述符解析
分析代码
class dis:
def __init__(self, fget, fset, fdel):
self.fget = fget
self.fset = fset
self.fdel = fdel
print('正在执行__init__方法.....')
def __set__(self, instance, value):
print('正在执行__set__方法.....')
print(instance, value)
def __delete__(self, instance):
print('正在执行__delete__方法')
print(instance)
def __get__(self, instance, owner):
print('正在执行__get__方法')
print(instance, owner)
class test:
def __init__(self, value = 10):
self.value = value
def fset(self, value):
self.value = value
def fget(self):
return self.value
def fdel(self):
del self.value
x = dis(fget, fset, fdel)
t = test()
print(t.x)
t.x = 20
print(t.x)
del t.x
输出
正在执行__init__方法.....
正在执行__get__方法
<__main__.test object at 0x0000016CA299CEE0> <class '__main__.test'>
None
正在执行__set__方法.....
<__main__.test object at 0x0000016CA299CEE0> 20
正在执行__get__方法
<__main__.test object at 0x0000016CA299CEE0> <class '__main__.test'>
None
正在执行__delete__方法
<__main__.test object at 0x0000016CA299CEE0>
当test类试图去通过x属性来访问自身的value属性时,就会自动跳转到执行dis类里面的__get__方法。
当试图通过x去修改value的属性时就会执行dis类里面的__set__方法。
当试图通过x去删除value的属性时会执行dis类里面的__del__方法。
然后我把它们的参数类型打印出来可以知道;
instance
参数指的是test
类的实例化对象t;
owner
指的是test
类;
因为这几个方法我只是把值给打印出来,并未给出有效操作的代码,就返回值一直是None
知道了上面之后我们可以实现property方法。
class dis:
def __init__(self, fget = None, fset = None, fdel = None):
self.fget = fget
self.fset = fset
self.fdel = fdel
def __set__(self, instance, value):
self.fset(instance, value)#这里fset的参数类型看test里面的fset就行,鸭子类型
def __delete__(self, instance):
self.fdel(instance)
def __get__(self, instance, owner):
return self.fget(instance)
以上大概就是property方法,然后再加上测试的代码
class test:
def __init__(self, value = 10):
self.value = value
def fset(self, value):
self.value = value
def fget(self):
return self.value
def fdel(self):
del self.value
x = dis(fget, fset, fdel)
t = test()
print(t.x)
t.x = 20
print(t.x)
del t.x
try:
print(t.x)
except AttributeError as reason:
print("出错啦"+str(reason))
这里是输出结果:
10
20
出错啦'test' object has no attribute 'value'