我已经开始阅读有关 Python 中的描述符的内容,并创建了一个小测试来查看属性访问的顺序是否与描述的相同。据我了解,当访问对象的属性时,会按以下顺序查看:
- in
type(instance).__dict__
- 如果给定名称的数据描述符存在,则返回其__get__
方法调用 - 在
实例.__dict__
- 如果
type(instance).__dict__
中存在非数据描述符,则返回__get__
方法调用 __getattr__
被调用。
现在,如果方法是给定类的类型实例的非数据描述符,则通过给定此描述符 __set__
函数/方法,它将使其成为数据描述符,因此可以覆盖此类函数,例如被阻止或操纵。不幸的是,这不起作用,我的问题很简单:为什么会出现这种情况? Python 是否在类初始化时“标记”数据和非数据描述符,还是我做错了什么?
class A:
def d(self):
pass
def __set__(self, instance, value):
print("Nothing to see here...")
A.__dict__['d'].__set__ = __set__
a = A()
a.d = "value"
print(a.d) # prints "value" instead of <bound method ...>
最佳答案
A.__dict__['d'].__set__ = __set__
,在本例中只是一种复杂的编写 A.d.__set__ = __set__
的方式,正在设置一个魔法实例上的方法。
这在 Python 中不起作用,魔术方法仅在类型上查找。而且你不能在类型上设置它,因为类型只是这里的内置函数类型。
但是,可以动态地将非数据描述符更改为数据描述符:
>>> class MyDescriptor:
... def __get__(self, instance, owner=None):
... return 'foo'
...
>>> class A:
... f = MyDescriptor()
...
>>> a = A()
>>> a.f
'foo'
>>> a.f = 'foo2'
>>> a.f
'foo2'
>>> MyDescriptor.__set__ = lambda self, instance, value: None
>>> a.f # now the descriptor takes precedence again over a.__dict__
'foo'
关于python - 为什么为方法描述符设置 __set__ 函数不会使其成为数据描述符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76863390/