Explicación de la distinción entre variables de clase y de instancia.
Las variables son esencialmente símbolos que representan un valor que estamos utilizando en un programa. La programación orientada a objetos permite utilizar las variables a nivel de clase o a nivel de instancia. El objetivo de este artículo es tener una clara distinción entre los tipos de variables que ofrece el modelo de objetos de Python y continúa discutiendo un comportamiento peculiar que podría conducir a algunos resultados sorprendentes, si se descuida. Según el modelo de objetos de Python, hay dos tipos de atributos de datos en los objetos de Python: variables de clase y variables de instancia.
Variables de clase – Declaradas dentro de la definición de la clase (pero fuera de cualquiera de los métodos de instancia). No están ligadas a ningún objeto de la clase en particular, por lo que se comparten entre todos los objetos de la clase. La modificación de una variable de clase afecta a todos los objetos instancia al mismo tiempo.
Variable de instancia – Declarada dentro del método constructor de la clase (el método __init__
). Están vinculados a la instancia del objeto particular de la clase, por lo tanto, el contenido de una variable de instancia son completamente independientes de una instancia del objeto a la otra.
Comencemos con un ejemplo corto y fácil de digerir:
class Car:
wheels = 4 # <- Class variable def __init__(self, name):
self.name = name # <- Instance variable
Se define la clase Car básica, sin florituras. Cada instancia de la misma tendrá ruedas variables de clase junto con el nombre de la variable de instancia. Vamos a instanciar la clase para acceder a las variables.
>>> jag = Car('jaguar')
>>> fer = Car('ferrari')>>> jag.name, fer.name
('jaguar', 'ferrari')>>> jag.wheels, fer.wheels
(4, 4)>>> Car.wheels
4
Acceder al nombre de la variable de instancia es bastante sencillo. Sin embargo hay un poco más de flexibilidad cuando se trata de acceder a la variable de clase. Como en el caso anterior, podemos acceder a las ruedas a través de la instancia del objeto o de la propia clase.
También intentar acceder al nombre a través de la clase resultará en un AttributeError ya que las variables de instancia son específicas del objeto y se crean cuando se invoca el constructor __init__
. Esta es la distinción central entre la clase y las variables de instancia.
>>> Car.name
AttributeError: type object 'Car' has no attribute 'name'
Ahora, vamos a suponer por el momento que nuestro coche Jaguar tiene 3 ruedas. (sí, es una estupidez, pero tenedlo en cuenta). Para representar eso en nuestro código, podemos modificar la variable ruedas.
>>> Car.wheels = 3
Lo que hemos hecho arriba hará que todos los coches tengan 3 ruedas ya que hemos modificado una variable de clase, que se aplicará a todas las instancias de la clase Coche.
>>> jag.wheels, fer.wheels
(3, 3)
Por tanto, modificar una variable de clase en el espacio de nombres de la clase afecta a todas las instancias de la clase. Retrocedamos el cambio y modifiquemos la variable wheels usando el objeto jag.
>>> Car.wheels = 4
>>> jag.wheels = 3
Esto nos dará el resultado que deseamos.
>>> jag.wheels, fer.wheels, Car.wheels
(3, 4, 4)
Aunque obtuvimos el resultado que queríamos, lo que sucedió detrás de escena es una nueva variable wheels que ha sido agregada al objeto jag y esta nueva variable hace sombra a la variable de clase con el mismo nombre, anulándola y ocultándola. Podemos acceder a ambas variables de ruedas como se indica a continuación.
>>> jag.wheels, jag.__class__.wheels
(3, 4)
De ahí que podamos concluir que jag.wheels = 3
creó una nueva variable de instancia con el mismo nombre que la variable de clase (ruedas). Este es un concepto importante a tener en cuenta.
Hacer uso de variables específicas de clase e instancia puede asegurar que nuestro código se adhiere al principio DRY para reducir la repetición dentro del código.
Saber esto siento que puede ser realmente útil y ahorrar muchas horas de depuración un día. 😇
Refiérete a mi este post para seguir leyendo sobre los distintos tipos de métodos (instancia, clase &estática) en Python.
Conclusiones
- Las variables de clase se comparten entre todos los objetos mientras que las variables de instancia son para datos exclusivos de cada instancia.
- Las variables de instancia anulan a las variables de clase que tienen el mismo nombre lo que puede introducir accidentalmente errores o comportamientos sorprendentes en nuestro código.