6

sto un po 'confuso da questo comportamento (con Python 3.2):Python doppia sottolineatura pressare

class Bar: 
    pass 

bar = Bar() 
bar.__cache = None 
print(vars(bar))  # {'__cache': None} 

class Foo: 
    def __init__(self): 
     self.__cache = None 

foo = Foo() 
print(vars(foo))  # {'_Foo__cache': None} 

Ho letto un po' su come doppio underscore causano nomi degli attributi per essere "storpiato", ma Mi sarei aspettato lo stesso nome, mitragliando in entrambi i casi sopra.

What is the meaning of a single- and a double-underscore before an object name?

Tutte le idee che cosa sta succedendo qui?

+4

Il punto di maneggevolezza è proprio quello di ** impedire ** al secondo caso di funzionare correttamente. L'intento è quello di nascondere l'attributo dal codice esterno. – millimoose

risposta

10

mutilazione dei nomi si verifica durante la valutazione di una dichiarazione class. Nel caso di Bar, l'attributo non è definito come parte della classe, ma piuttosto aggiunto a un oggetto specifico dopo il fatto.

(A dire il vero, che non può essere del tutto corretto mutilazione dei nomi può verificarsi durante la valutazione del metodo __new__,.. Non so Ma a prescindere, il vostro __cache viene aggiunto in modo esplicito ad un singolo oggetto, non aggiunta dal codice della classe .)

+4

È alterato durante la compilazione. Puoi usare la funzione 'dis.dis()' per vedere questo, basta eseguire il comando 'import dis; dis.dis (Foo .__ init __) 'per vedere che il nome è già stato storpiato. –

+0

molto utile, grazie per la spiegazione – gnr

7

Dal docs

privato nome storpiatura: Quando un identificatore che si verifica testualmente in una definizione di classe inizia con due o più caratteri di sottolineatura e non termina in due o più underscore, è considerato un nome privato di quella classe. I nomi privati ​​vengono trasformati in un modulo più lungo prima che il codice venga generato per loro. La trasformazione inserisce il nome della classe davanti al nome, con i caratteri di sottolineatura principali rimossi, e un singolo carattere di sottolineatura inserito davanti al nome della classe. Ad esempio, l'identificatore __spam che si verifica in una classe denominata Ham sarà trasformato in _Ham__spam. Questa trasformazione è indipendente dal contesto sintattico in cui viene utilizzato l'identificatore. Se il nome trasformato di è estremamente lungo (più lungo di 255 caratteri), potrebbe verificarsi il troncamento definito dall'implementazione . Se il nome della classe consiste solo di caratteri di sottolineatura, non viene eseguita alcuna trasformazione.

si sta assegnando la vostra proprietà dopo che la classe è stata definita

+0

Il collegamento ai documenti è interrotto –