6

我正在编写一个需要访问私有变量的装饰器并发现了这种差异。谁能解释一下?

(Python 2.5)

对于类中定义的属性,命名修饰按预期工作:

>>> class Tester(object):
...    __foo = "hi"

>>> t = Tester()
>>> t._Tester__foo
'hi'

实例属性不起作用(这是我们应该做的正确的方式?)

>>> class Tester(object):
...     def __init__(self):
...         self.__foo = "hi"

>>> t = Tester()
>>> t._Tester__foo
AttributeError: 'Tester' object has no attribute '_Tester__foo'

PS“类属性”是正确的词吗?它们不是静态的,但是如果您将其中之一设为列表或其他一些可变类型,则它是共享的...

更新

实际上,第二个示例也可以正常工作。这是一个硬件问题(重启有帮助)。

4

1 回答 1

10

这实际上是正确的。

名称修改发生在类创建时;任何引用重整名称的函数也会被调整。

我无法重现您的示例,至少不能在 Mac 上的 Python 版本 2.4、2.5、2.6、3.1 和 3.2 中重现:

>>> class Tester(object):
...     def __init__(self):
...         self.__foo = "hi"
... 
>>> Tester()._Tester__foo
'hi'
>>> Tester().__foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Tester' object has no attribute '__foo'

如果你反汇编函数字节码,你可以看到名称也被破坏了:

>>> import dis
>>> dis.dis(Tester.__init__)
  3           0 LOAD_CONST               1 ('hi')
              3 LOAD_FAST                0 (self)
              6 STORE_ATTR               1 (_Tester__foo)
              9 LOAD_CONST               0 (None)
             12 RETURN_VALUE        

我检查了编译器源代码所有名称都通过 mangler 运行,至少自 2002 年以来一直保持相同的代码路径。

是的,类属性和实例属性是正确的术语。类属性始终是共享的,但分配实例上的属性会分配给实例。改变列表或其他可变对象与属性分配不同。

于 2012-09-21T20:44:12.300 回答