【问题标题】:How does python interpreter decides when to invokes the __set__ and __get__ methods and when not to? [duplicate]python 解释器如何决定何时调用 __set__ 和 __get__ 方法以及何时不调用? [复制]
【发布时间】: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


【解决方案1】:

这是因为在查找实例类的属性时使用了描述符。如果它是一个实例属性,它不会受到描述符协议的影响。

此类问题的一个很好的资源是 ionel 的关于元类的博客,其中包含这张图片,该图片还显示了何时使用描述符:

(图片复制自here

因为cdescrclass.__dict__ 中并且有__get____set__ 它将返回描述符__get__ 返回的内容。然而,因为idescr 不在class.__dict__ 中,它只会返回存储在instance.__dict__ 中的内容。

【讨论】:

    猜你喜欢
    • 2011-04-17
    • 1970-01-01
    • 2021-12-19
    • 2012-08-31
    • 1970-01-01
    • 2017-10-31
    • 2016-08-20
    • 1970-01-01
    相关资源
    最近更新 更多