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
答案 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
的所有实例之间共享。
目前还不清楚你要在这里实现什么,所以很难说如何“修复”这个问题。一些一般原则是:
Cls
中使用self
。要存储特定于实例的数据,您需要使用__get__
。__set__
而根本不写自己的描述符。如果您“修复”了上面描述的描述符,它仍然是无用的,因为它不会执行instance
尚未执行的操作。