首先,property装饰器是经过数据描述符实现的。用法很简单,你们应该都知道,这里就不细说了。html
这里主要分析一下property是如何经过描述符实现的。python
class Property: def __init__(self, fget): self.fget = fget # 为实例增长方法,这里的方法是未绑定实例的,不会自动传入实例self self.fset = None # 同上,未绑定实例 def __get__(self, instance, owner): if instance is not None: return self.fget(instance) # 调用原方法,传入实例self return self def __set__(self, instance, value): self.fset(instance, value) # 调用原方法,传入实例self和value def setter(self, func): self.fset = func # 更新属性 return self class A: def __init__(self, data): self._data = data @Property # data = Property(data) 描述符实例 def data(self): return self._data @data.setter # data = data.setter(data) 更新属性,并返回描述符实例 def data(self, value): self._data = value
访问函数
a = A(100) print(a.data) # 访问描述符实例,调用__get__()方法 # 100 执行过程以下: 1. 在装饰器中,data变量指向Property(func)描述符实例 2. 原data()函数被赋值给fget变量 3. a.data就是访问描述符实例,触发调用__get__()方法 4. 最后,调用fget()也就是原data()方法,并传入owner class的实例,亦即调用data(self)
赋值code
a.data = 200 # 访问描述符实例,调用__set__()方法 print(a.data) # 访问描述符实例,调用__get__()方法 # 200 执行过程以下: 1. 在装饰器中,data变量指向data.setter(func)描述符实例。注意,后面的data是__get__()方法返回的描述符实例 2. 原data()函数被赋值给fset变量 3. 赋值操做触发调用__set__方法 4. 最后,调用fset也就是原data()方法,并传入owner class的实例和要赋的值,亦即调用data(self, value)
这里涉及到装饰器,须要对装饰器和面向对象有足够的了解才能弄明白当中的变量传递,但愿你不会被挡住。htm
参考:
https://docs.python.org/3/library/functions.html#property对象