¿Debo usar atributos de instancia o clase si solo habrá una instancia? [cerrado]
Tengo clases de Python, de las cuales necesito solo una instancia en tiempo de ejecución, por lo que sería suficiente tener los atributos solo una vez por clase y no por instancia. Si hubiera más de una instancia (lo cual no sucederá), todas las instancias deberían tener la misma configuración. Me pregunto cuál de las siguientes opciones sería mejor o más "idiomática" de Python.
Variables de clase:
class MyController(Controller):
path = "something/"
children = [AController, BController]
def action(self, request):
pass
Variables de instancia:
class MyController(Controller):
def __init__(self):
self.path = "something/"
self.children = [AController, BController]
def action(self, request):
pass
Si de todos modos solo tiene una instancia, es mejor crear todas las variables por instancia, simplemente porque se accederá a ellas (un poco) más rápido (un nivel menos de "búsqueda" debido a la "herencia" de clase a instancia). y no hay desventajas que puedan compararse con esta pequeña ventaja.
Haciéndome eco del consejo de Mike y Alex y agregando mi propio color...
El uso de atributos de instancia es lo típico... el Python más idiomático. Los atributos de clase no se utilizan tanto, ya que sus casos de uso son específicos. Lo mismo ocurre con los métodos estáticos y de clase frente a los métodos "normales". Son construcciones especiales que abordan casos de uso específicos; de lo contrario, es código creado por un programador aberrante que quiere demostrar que conoce algún rincón oscuro de la programación en Python.
Alex menciona en su respuesta que el acceso será (un poco) más rápido debido a un nivel menos de búsqueda... déjenme aclarar más para aquellos que aún no saben cómo funciona esto. Es muy similar al acceso variable, cuyo orden de búsqueda es:
- lugareños
- no locales
- globales
- incorporados
Para el acceso a atributos, el orden es:
- instancia
- clase
- clases base según lo determinado por el MRO (orden de resolución del método)
Ambas técnicas funcionan de manera "de adentro hacia afuera", lo que significa que primero se verifican los objetos más locales y luego las capas externas se verifican sucesivamente.
En el ejemplo anterior, digamos que está buscando el path
atributo. Cuando encuentra una referencia como " self.path
", Python buscará primero los atributos de la instancia en busca de coincidencias. Cuando eso falla, verifica la clase desde la cual se creó la instancia del objeto. Finalmente, buscará las clases base. Como dijo Alex, si su atributo se encuentra en la instancia, no es necesario buscar en otra parte, de ahí su pequeño ahorro de tiempo.
Sin embargo, si insiste en los atributos de clase, necesita esa búsqueda adicional. O bien , su otra alternativa es hacer referencia al objeto a través de la clase en lugar de la instancia, por ejemplo, MyController.path
en lugar de self.path
. Esa es una búsqueda directa que evitará la búsqueda diferida, pero como Alex menciona a continuación, es una variable global, por lo que pierdes esa parte que pensabas que ibas a guardar (a menos que crees una referencia local al nombre de clase [global] ).
La conclusión es que debes usar atributos de instancia la mayor parte del tiempo. Sin embargo, habrá ocasiones en las que un atributo de clase sea la herramienta adecuada para el trabajo. El código que usa ambos al mismo tiempo requerirá la mayor diligencia, porque usarlo self
solo le dará el objeto de atributo de instancia y acceso oculto al atributo de clase del mismo nombre. En este caso, debe utilizar el acceso al atributo por el nombre de la clase para poder hacer referencia a él.