2014-02-18 37 views
1
>>> class foo(): 
...  @property 
...  def o(self): 
...    return 'o' 
... 
>>> f = foo() 
>>> f.o 
'o' 
>>> f.__dict__['o'] = 'f' 
>>> f.o 
'f' 
>>> class foo(object): 
...  @property 
...  def o(self): 
...    return 'o' 
... 
>>> f = foo() 
>>> f.o 
'o' 
>>> f.__dict__['o'] = 'f' 
>>> f.o 
'o' 

__dict__集合刚刚没有出现。任何想法为什么?Python新风格类不能使用__dict__来更新属性属性

我想也许Python对待属性的内部不同,但我不确定它,如果你自己写一个属性类,该集合就会工作,否则不会。

+1

你应该看一看以各种方式来改变python中的[attribute access](http://docs.python.org/2/reference/datamodel.html#customizing-attribute-access)。特别是'@ property'创建一个描述符(参见链接的材料来理解它是什么以及它是如何工作的)。 – Bakuriu

回答

3
@property 
def o(self): 
    return 'o' 

这是一个非数据描述符,即没有定义setter的属性。因此一个实例属性可以覆盖这个属性。

docs

如果一个实例的字典里有一个同名的条目作为 非数据描述符,词典条目优先。

因此,要更新属性,还要定义其setter方法。

,并且不使用实例的__dict__访问了二传手的setter或getter,内部f.o = 'f'实际上被转换为:

type(f).__dict__['o'].__set__(f, 'f') 

演示:

class Foo: 

    def __init__(self): 
     self._o = 'o' 

    @property 
    def o(self): 
     return self._o 

    @o.setter 
    def o(self, val): 
     self._o = val 

>>> f = Foo() 
>>> f.o 
'o' 
>>> type(f).__dict__['o'].__set__(f, 'f') 
>>> f.o 
'f' 
>>> f.o = 'zzzz' #this is equivalent to the previous call. 
>>> f.o 
'zzzz' 
>>> type(f).__dict__['o'].__set__(f, 'foo') 
>>> f.o 
'foo' 
+0

非常感谢。 – fengsp

+1

我知道在这里使用'__dict__''可能会有一些教育优势(尽管我看不到它),但为什么不提到''getattr'' /''setattr''?也许我完全没有理解上下文。 –

+0

@JonasWielicki当然'setattr'和'getattr'是比那个巨大的'__dict__'调用更好的选择,但我认为OP的问题是关于如何使用'__dict__'来做到这一点。 –