6

Estaba escribiendo un decorador que necesita acceder a variables privadas y encontró esta discrepancia. ¿Alguien puede explicar esto?Nombre "privado" de Python que mapea e instancia contra atributos de clase

(Python 2.5)

nombres mangling funciona como se espera para los atributos definidos en la clase:

atributos de instancia no funcionan (y esta es la forma en que se supone que debemos hacer las cosas bien?)

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

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

PS ¿El "atributo de clase" es la palabra correcta para estos? Ellos no son estáticos, pero si haces una de esas una lista, o algún otro tipo mutable, es compartida ...

actualización

De hecho, el segundo ejemplo funciona bien, también. Fue un problema de hardware (reinicio ayudado).

+2

El atributo de clase es la palabra correcta. Y son * siempre * compartidos. La mutabilidad no importa. Casi nunca importa, excepto cuando se pregunta si puedes mutar un objeto dado. – delnan

+0

¿Puedo enviar esta pregunta? ¿O alguien ve valor para mantenerlo? No puedo reproducir mi problema original. Parece que funciona como se esperaba. – Rafe

+1

Mejor déjalo, ya que @MartijnPieters hizo todo el recorrido para probar el problema en muchas pruebas de Python. – jsbueno

Respuesta

9

Eso es en realidad no correcto.

El cambio de nombre se produce en el momento de creación de la clase; cualquier función que se refiera a nombres destrozados también se ajusta.

No puedo reproducir el ejemplo, al menos no en Python versiones 2.4, 2.5, 2.6, 3.1 y 3.2 en el 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' 

Si desmonta el código de bytes función se puede ver el nombre ha sido mutilado así:

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

he comprobado la compiler source y todos los nombres se ejecutan a través de la trituradora, una ruta de código que se ha mantenido la misma desde 2002 por lo menos.

Y sí, los atributos de clase y los atributos de instancia son los términos correctos. Los atributos de clase siempre se comparten, pero la asignación a asigna un atributo en una instancia a la instancia. La mutación de una lista u otros objetos mutables no es lo mismo que la asignación de atributos.

+0

También funciona con 3.2. – delnan

+0

Tienes razón. No tengo idea de lo que pasó allí. Yo reinicio mi computadora, así que tendré que llamarlo un problema de TI, "¿Has intentado apagarlo y encenderlo de nuevo?" ;) – Rafe

Cuestiones relacionadas