6

Stavo scrivendo un decoratore che ha bisogno di accedere a variabili private e trovato questa discrepanza. Qualcuno può spiegarlo?Python "privato" nome mangling e istanza contro attributi della classe

(Python 2.5)

Naming pressare opere come previsto per gli attributi definiti nella classe:

attributi di istanza non funzionano (e questo è il modo in cui siamo tenuti a farlo bene?)

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

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

PS "Attributo di classe" è la parola giusta per questi? Essi non sono statici, ma se fate uno di quelli un elenco, o qualche altro tipo mutabile, si è condiviso ...

Aggiornamento

Infatti, secondo esempio funziona bene, anche. Era un problema hardware (riavvio aiutato).

+2

L'attributo di classe è la parola giusta. E sono * sempre * condivisi. La mutabilità non ha importanza. Praticamente non importa mai, tranne quando ti chiedi se riesci a mutare un dato oggetto. – delnan

+0

Posso nuke questa domanda? O qualcuno vede valore nel mantenerlo? Non riesco a riprodurre il mio problema originale. Sembra funzionare come previsto. – Rafe

+1

Lasciamo perdere, dato che @MartijnPieters ha fatto tutto il possibile per testare il problema in molti test di Python. – jsbueno

risposta

9

che in realtà non corretta.

mutilazione dei nomi avviene al momento della creazione della classe; anche eventuali funzioni che si riferiscono a nomi storpiati vengono regolate.

non riesco a riprodurre il tuo esempio, almeno non in Python le versioni 2.4, 2.5, 2.6, 3.1 e 3.2 su 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' 

Se si smonta la funzione di bytecode si può vedere il nome è stato storpiato così:

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

ho controllato il compiler source e tutti nomi sono gestiti attraverso il Mangler, un percorso di codice che è rimasta la stessa dal 2002 almeno.

E sì, gli attributi di classe e gli attributi di istanza sono i termini corretti. Gli attributi di classe sono sempre condivisi, ma dall'assegnazione a un attributo su un'istanza viene assegnato all'istanza. La modifica di una lista o di altri oggetti mutabili non equivale all'assegnazione degli attributi.

+0

Funziona anche con 3.2. – delnan

+0

Hai ragione. Non ho idea di cosa sia successo lì. Mi capita di riavviare il mio computer, quindi dovrò semplicemente chiamarlo un problema IT, "Hai provato a spegnerlo e riaccenderlo?" ;) – Rafe

Problemi correlati