6

Ich schrieb einen Dekorator, der auf private Variablen zugreifen muss und diese Diskrepanz gefunden. Kann das jemand erklären?Python "private" Name Mangling und Instanz vs Klasse Attribute

(Python 2.5)

Naming Mangeln Werke wie für Attribute erwartet in der Klasse definiert:

Instanz Attribute funktionieren nicht (und das ist die Art, wie wir sollen, es richtig machen?)

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

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

PS Ist "Klassenattribut" das richtige Wort für diese? Sie sind nicht statisch, sondern, wenn Sie einer von denen, machen Sie eine Liste oder eine andere veränderbare Art ist es geteilt ...

aktualisieren

Tatsächlich zweites Beispiel funktioniert gut, auch. Es war ein Hardwareproblem (Neustart half).

+2

Klassenattribut ist das richtige Wort. Und sie werden * immer * geteilt. Mutabilität spielt keine Rolle. Es ist ziemlich egal, außer wenn Sie fragen, ob Sie ein bestimmtes Objekt mutieren können. – delnan

+0

Kann ich diese Frage beantworten? Oder sieht irgendjemand Wert darin, es zu behalten? Ich kann mein ursprüngliches Problem nicht reproduzieren. Es scheint zu funktionieren wie erwartet. – Rafe

+1

Lieber herum, da @MartijnPieters den Test in vielen Python-Tests getestet hat. – jsbueno

Antwort

9

Das ist eigentlich nicht richtig.

Name Mangling findet zur Klassenerstellungszeit statt; Alle Funktionen, die sich auf verstümmelte Namen beziehen, werden ebenfalls angepasst.

ich Ihr Beispiel nicht wiedergeben kann, zumindest nicht in Python-Versionen 2.4, 2.5, 2.6, 3.1 und 3.2 auf dem 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' 

Wenn Sie die Funktion Bytecode zerlegen Sie den Namen verstümmelt wurde sehen auch:

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

ich die compiler source und alle Namen überprüft haben, werden durch die mangler laufen, einen Codepfad, der die gleiche seit 2002 mindestens geblieben ist.

Und ja, Klassenattribute und Instanzattribute sind die richtigen Begriffe. Klassenattribute werden immer gemeinsam verwendet, aber die Zuordnung zu einem Attribut für eine Instanz wird der Instanz zugewiesen. Das Mutieren einer Liste oder anderer veränderbarer Objekte entspricht nicht der Zuweisung von Attributen.

+0

Funktioniert auch mit 3.2. – delnan

+0

Sie haben Recht. Ich habe keine Ahnung, was dort passiert ist. Ich starte meinen Computer neu, daher muss ich es nur als IT-Problem bezeichnen. "Haben Sie versucht, es wieder aus- und wieder einzuschalten?" ;) – Rafe