Tengo clases de Python, de las cuales solo necesito 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 que 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" en 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
Respuestas:
Si solo tiene una instancia de todos modos, es mejor hacer 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 inconvenientes para sopesar esta pequeña ventaja.
fuente
python -mtimeit
, pero después de hacerlo en python3.4, noto que acceder a unaint
variable de clase es en realidad de 5 a 11 nanosegundos más rápido que la misma variable de instancia en mi antigua estación de trabajo, no estoy seguro de qué codepath lo hace así.Repitiendo aún más los consejos de Mike y Alex y agregando mi propio color ...
El uso de atributos de instancia es el 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 un código creado por un programador aberrante que quiere presumir que conocen algún rincón oscuro de la programación de Python.
Alex menciona en su respuesta que el acceso será (un poco) más rápido debido a un nivel menos de búsqueda ... permítanme 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:
Para el acceso a atributos, el orden es:
Ambas técnicas funcionan de manera "de adentro hacia afuera", lo que significa que los objetos más locales se verifican primero, luego las capas externas se verifican sucesivamente.
En su ejemplo anterior, digamos que está buscando el
path
atributo. Cuando encuentra una referencia como "self.path
", Python buscará primero en los atributos de la instancia una coincidencia. Cuando eso falla, verifica la clase desde la que se creó la instancia del objeto. Finalmente, buscará las clases base. Como dijo Alex, si su atributo se encuentra en la instancia, no necesita buscar en otro lado, de ahí su pequeño ahorro de tiempo.Sin embargo, si insiste en los atributos de clase, necesita esa búsqueda adicional. O su otra alternativa es hacer referencia al objeto a través de la clase en lugar de la instancia, por ejemplo, en
MyController.path
lugar deself.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 pierde ese bit que pensó que iba a guardar (a menos que cree una referencia local al nombre de clase [global] ).La conclusión es que debe 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 uso de código que use ambos al mismo tiempo requerirá la mayor diligencia, porque el uso
self
solo le dará el objeto de atributo de instancia y el acceso de sombras al atributo de clase del mismo nombre. En este caso, debe utilizar el acceso al atributo por el nombre de la clase para hacer referencia a él.fuente
MyController
se busca en los globales, por lo que el costo total es más alto queself.path
dondepath
es una variable de instancia (ya queself
es local al método == búsqueda súper rápida).En caso de duda, probablemente desee un atributo de instancia.
Los atributos de clase se reservan mejor para casos especiales en los que tienen sentido. El único caso de uso muy común son los métodos. No es raro usar atributos de clase para constantes de solo lectura que las instancias necesitan saber (aunque el único beneficio de esto es si también desea acceso desde fuera de la clase), pero ciertamente debe tener cuidado al almacenar cualquier estado en ellas. , que rara vez es lo que quieres. Incluso si solo tendrá una instancia, debe escribir la clase como lo haría con cualquier otra, lo que generalmente significa usar atributos de instancia.
fuente
avoid global variables
y su definición es que las variables globales también son variables que se declaran como atributos de clase. Sin embargo, la propia guía de estilo de Python ( PEP-8 ) debería ser el primer lugar al que acudir para preguntas de este tipo. Entonces su propia mente debería ser la herramienta elegida (por supuesto, también puede obtener ideas de Google, por ejemplo).La misma pregunta en Rendimiento de acceder a variables de clase en Python : el código aquí adaptado de @Edward Loper
Las variables locales son las más rápidas de acceder, prácticamente vinculadas con las variables del módulo, seguidas de las variables de clase, seguidas de las variables de instancia.
Hay 4 ámbitos desde los que puede acceder a las variables:
La prueba:
El resultado:
fuente