Python" частное " имя искажение и экземпляр против атрибутов класса


Я писал декоратор, которому нужен доступ к частным переменным, и обнаружил это несоответствие. Кто-нибудь может это объяснить?

(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'

P. S. является "атрибут класса" правильное слово для этого? Они не статичны, но если вы сделаете один из них списком или каким-то другим изменяемым типом, это будет общий...

Обновить

На самом деле, второй пример тоже отлично работает. Это была аппаратная проблема (перезагрузка помогла).
1 6

1 ответ:

Это на самом деле Не Правильно.

Искажение имен происходит во время создания класса; все функции, которые ссылаются на искаженные имена, также настраиваются.

Я не могу воспроизвести ваш пример, по крайней мере, в версиях Python 2.4, 2.5, 2.6, 3.1 и 3.2 на Mac:

>>> 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        

Я проверил исходный код компилятора и Все имена проходят через The mangler, кодовый путь, который оставался неизменным по крайней мере с 2002 года.

И да, атрибуты класса и атрибуты экземпляра-правильные термины. Атрибуты класса всегда являются общими, но присваивание атрибута в экземпляре присваивает экземпляр. Изменение списка или других изменяемых объектов-это не то же самое, что назначение атрибутов.