Aunque la respuesta aceptada es acertada, me gustaría agregar una pequeña descripción.
Hagamos un pequeño ejercicio.
En primer lugar, defina una clase de la siguiente manera:
class A:
temp = 'Skyharbor'
def __init__(self, x):
self.x = x
def change(self, y):
self.temp = y
entonces que tenemos aqui?
- Tenemos una clase muy simple que tiene un atributo
temp
que es una cadena
- Un
__init__
método que estableceself.x
- Un método de cambio establece
self.temp
Bastante sencillo hasta ahora, ¿sí? Ahora comencemos a jugar con esta clase. Inicialicemos esta clase primero:
a = A('Tesseract')
Ahora haga lo siguiente:
>>> print(a.temp)
Skyharbor
>>> print(A.temp)
Skyharbor
Bueno, a.temp
funcionó como se esperaba, pero ¿cómo demonios A.temp
funcionó? Bueno, funcionó porque temp es un atributo de clase. Todo en Python es un objeto. Aquí A es también un objeto de clase type
. Por lo tanto, el atributo temp es un atributo mantenido por la A
clase y si cambia el valor de temp a través de A
(y no a través de una instancia de a
), el valor cambiado se reflejará en toda la instancia de A
clase. Avancemos y hagamos eso:
>>> A.temp = 'Monuments'
>>> print(A.temp)
Monuments
>>> print(a.temp)
Monuments
¿Interesante no? Y tenga en cuenta que id(a.temp)
y id(A.temp)
siguen siendo los mismos .
Cualquier objeto de Python recibe automáticamente un __dict__
atributo, que contiene su lista de atributos. Investiguemos qué contiene este diccionario para nuestros objetos de ejemplo:
>>> print(A.__dict__)
{
'change': <function change at 0x7f5e26fee6e0>,
'__module__': '__main__',
'__init__': <function __init__ at 0x7f5e26fee668>,
'temp': 'Monuments',
'__doc__': None
}
>>> print(a.__dict__)
{x: 'Tesseract'}
Tenga en cuenta que el temp
atributo se enumera entre A
los atributos de la clase mientras que x
se enumera para la instancia.
Entonces, ¿cómo es que obtenemos un valor definido de a.temp
si ni siquiera está listado para la instancia a
? Bueno, esa es la magia del __getattribute__()
método. En Python, la sintaxis punteada invoca automáticamente este método, por lo que cuando escribimos a.temp
, Python se ejecuta a.__getattribute__('temp')
. Ese método realiza la acción de búsqueda de atributos, es decir, encuentra el valor del atributo buscando en diferentes lugares.
La implementación estándar de __getattribute__()
búsquedas primero el diccionario interno ( dict ) de un objeto, luego el tipo del objeto en sí. En este caso se a.__getattribute__('temp')
ejecuta primero a.__dict__['temp']
y luegoa.__class__.__dict__['temp']
Bien, ahora usemos nuestro change
método:
>>> a.change('Intervals')
>>> print(a.temp)
Intervals
>>> print(A.temp)
Monuments
Bueno, ahora que lo hemos usado self
, print(a.temp)
nos da un valor diferente de print(A.temp)
.
Ahora, si comparamos id(a.temp)
y id(A.temp)
, serán diferentes.
list
como nombre de atributo.list
es una función integrada para construir una nueva lista. Deberías escribir clases de nombres con mayúscula.