属性上的意外名称查找

时间:2016-04-13 19:10:22

标签: python

考虑以下代码:

class Foo(object):
    @property
    def func(self):
        self.__dict__['func'] = 1 
        return 2

f = Foo()
print f.func
print f.func

打印2 2。为什么,第二次,它不打印1

2 个答案:

答案 0 :(得分:3)

因为f.func其中fFoo的实例且funcproperty描述符触发器

Foo.func.__get__(f)

(见Descriptor protocol)。

self.__dict__['func'] = 1修改f实例的基础字典。它不会更改func类的Foo属性。

Foo.func优先于f.func = 1 ,新创建的实例变量),因为

  

如果实例的字典具有与数据同名的条目   描述符,数据描述符优先。

(从上面的链接复制)。

如果要替换属性,则必须为Foo.func分配内容:

class Foo(object):
    @property
    def func(self):
        Foo.func = 1 
        return 2

f = Foo()
print(f.func) # 2
print(f.func) # 1

答案 1 :(得分:2)

根据this post,属性查找过程按此顺序排列:

  
      
  1. 如果attrname是objectname的特殊(即Python提供的)属性,则返回它。
  2.   
  3. 检查objectname .__ class __.__ dict__是否为attrname。如果它存在且是数据描述符,则返回描述符结果。搜索所有   objectname .__ class__的基础为同一案件。
  4.   
  5. 检查attrname的objectname .__ dict__,如果找到则返回。如果objectname是一个类,也搜索它的基础。如果它是一个类和一个   描述符存在于其中或其基础中,返回描述符结果。
  6.   
  7. 检查objectname .__ class __.__ dict__是否为attrname。如果它存在且是非数据描述符,则返回描述符结果。如果它   存在,而不是描述符,只需返回它。如果它存在并且是   数据描述符,我们不应该在这里,因为我们会回来   在第2点。搜索对象名.__ class__的所有基础同样的情况。
  8.   
  9. 提升属性错误。
  10.   

属性修饰器将一个键值对添加到对象的类' __dict__,因此在步骤2中找到它。在步骤3中检查添加到对象__dict__的名称。因此,在这两者之间,属性优先。