【发布时间】:2018-03-01 22:43:25
【问题描述】:
假设我们定义如下python描述符
class FooDescriptor():
def __init__(self, name='foo', initval='initval'):
self.name = name
self.val = initval
def __get__(self, instance, cls):
print("invoke get {} in instance {} in class {}".format(self.name, instance, cls))
return self.val
def __set__(self, instance, val):
print("invoke set {} in instance {}".format(self.name, instance))
self.val = val
现在如果我们定义类Foo 具有FooDescriptor 类型的类属性和相同类型的实例属性:
class Foo():
cdescr = FooDescriptor(name='class attribute descr', initval=1)
def __init__(self):
self.idescr = FooDescriptor(name='instance attribute descr', initval=2)
我们得到了类描述符的期望行为:
>>> foo = Foo()
>>> foo.cdescr
invoke get class attribute descr in instance <__main__.Foo object at 0x10189ecc0> in class <class '__main__.Foo'>
1
>>> foo.cdescr = 100
invoke set class attribute descr in instance <__main__.Foo object at 0x10189ecc0>
>>> foo.cdescr
invoke get class attribute descr in instance <__main__.Foo object at 0x10189ecc0> in class <class '__main__.Foo'>
100
但是对于实例属性idescr,描述符对象的__set__ 和__get__ 方法在访问或设置属性时不会被调用:
>>> foo.idescr
<__main__.FooDescriptor object at 0x10189ecf8>
>>> foo.idescr = 120
>>> foo.idescr
120
>>> type(foo.idescr)
<class 'int'>
如果能更好地理解描述符的范围以及当看到属性协议. 时python 如何决定调用它们的__set__ 和__get__,我们将不胜感激。
【问题讨论】:
-
描述符协议不适用于实例属性。描述符是 class 对象的成员,而不是实例对象
标签: python