我正在查看python的描述符文档here,让我思考的声明是:
对于对象,机制位于object.__getattribute__()
,将b.x
转换为type(b).__dict__['x'].__get__(b, type(b))
声明b.x into type(b).__dict__['x'].__get__(b, type(b))
的最后部分导致此处发生冲突。根据我的理解,如果我们在实例上查找属性,那么正在查找instance.__dict__
,如果我们没有找到任何type(instance).__dict__
被引用。
在我们的示例中,b.x
应该被评估为:
b.__dict__["x"].__get__(b, type(b))
代替
type(b).__dict__['x'].__get__(b, type(b))
这种理解是否正确?或者我在解释的某个地方出错了? 任何解释都会有所帮助。
感谢。
我也在添加第二部分:
为什么实例属性不遵循描述符协议?例如:参考下面的代码:
>>> class Desc(object):
... def __get__(self, obj, type):
... return 1000
... def __set__(self, obj, value):
... raise AttributeError
...
>>>
>>> class Test(object):
... def __init__(self,num):
... self.num = num
... self.desc = Desc()
...
>>>
>>> t = Test(10)
>>> print "Desc details are ", t.desc
Desc details are <__main__.Desc object at 0x7f746d647890>
感谢您帮助我。
答案 0 :(得分:1)
您的理解不正确。 x
很可能根本没有出现在实例的字典中;描述符对象出现在类的dict或其中一个超类的字典中。
让我们举个例子:
class Foo(object):
@property
def x(self):
return 0
def y(self):
return 1
x = Foo()
x.__dict__['x'] = 2
x.__dict__['y'] = 3
Foo.x
和Foo.y
都是描述符。 (属性和函数都实现了描述符协议。)
当我们访问x.x
时:
>>> x.x
0
我们没有从x
的词汇中获得价值。相反,由于Python在x
中找到名为Foo.__dict__
的数据描述符,因此调用
Foo.__dict__['x'].__get__(x, Foo)
并返回结果。数据描述符胜过实例dict。
另一方面,如果我们尝试x.y
:
>>> x.y
3
我们得到3,而不是绑定的方法对象。函数没有__set__
或__delete__
,因此实例dict会覆盖它们。
至于你问题的新第2部分,描述符在实例dict中不起作用。考虑如果他们这样做会发生什么:
class Foo(object):
@property
def bar(self):
return 4
Foo.bar = 3
如果描述符在实例dict中起作用,则对Foo.bar
的赋值将在Foo
的dict中找到描述符并调用Foo.__dict__['bar'].__set__
。描述符的__set__
方法必须处理在类和实例上设置属性,并且它必须以某种方式区分,即使面对元类。没有令人信服的理由以这种方式使协议复杂化。