Python描述符的特定实现

时间:2013-10-06 04:35:36

标签: python python-3.x python-3.3

class Cls():

    def __init__(self, start):
        self.value = start


    class Desc():
        def __get__(self, instance ,owner):
            print("In Descriptor's __get__method")
            return self.value
        def __set__(self, instance, start):
            print("In Descriptor's __set__ method")
            self.value = start

    value = Desc()

X = Cls('Hello')
X.value = "Hi"

描述符的上述实现对我来说是模糊的。 X.value和Cls.value引用同一个对象并且是str类。但是Cls .__ dict __ ['value']是描述符对象。有两种类型分配给名称“值”。

有人可以解释一下吗?这个特定实现背后的逻辑是什么?为什么Cls.value或X.value不是描述符对象。我正在使用python 3.3

1 个答案:

答案 0 :(得分:4)

对于两件事,使用名称value令人困惑:一个是Cls的属性,其值是描述符对象。另一个是该描述符对象的属性,也就是其值为字符串的属性。

要记住的关键是,只有一个描述符对象,在所有类的实例中共享。在self.value = start方法中执行__set__时,self引用描述符对象,因此您在描述符对象本身上设置“值”属性,而不是{{1}实例。 (如果您将其更改为Cls,则会收到递归错误,因为这会尝试再次调用instance.value = start。)

如果您创建了多个类的实例,您将看到正在发生的事情:

__set__

请注意,创建>>> x = Cls("oops") In Descriptor's __set__ method >>> y = Cls("dang") In Descriptor's __set__ method >>> x.value In Descriptor's __get__method 'dang' >>> Cls.__dict__['value'].value 'dang' 已更改y。这是因为只有一个描述符对象,它只有一个“value”属性,因此该值在x.value的所有实例之间共享。

目前还不清楚你要在这里实现什么,所以很难说如何“修复”这个问题。一些一般原则是:

  1. 除非您要存储类级信息,否则请勿在{{1​​}}和Cls中使用self。要存储特定于实例的数据,您需要使用__get__
  2. 即使您执行上述操作,也不要使用描述符属性本身的相同名称和存储其数据的隐藏属性,否则您将自行踩脚。
  3. 除非你想做一些非常奇特的事情,否则你可能只能使用__set__而根本不写自己的描述符。如果您“修复”了上面描述的描述符,它仍然是无用的,因为它不会执行instance尚未执行的操作。