Las variables de instancia frente variables de clase en Python


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 Python "idiomático".

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
Author: ndmeiri, 2010-04-26

3 answers

Si de todos modos solo tiene una instancia, es mejor hacer que 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 la clase a la instancia), y no hay inconvenientes que pesen contra esta pequeña ventaja.

 146
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-26 15:16:24

Haciéndose eco de los consejos de Mike y Alex y añadiendo mi propio color...

El uso de atributos de instancia es el típico Python más idiomático. los atributos de clase no se usan con frecuencia not al menos no en el código de producción en mis últimos 13 años consecutivos de Python. lo mismo es cierto para los métodos estáticos y de clase... simplemente no es muy común a menos que haya un caso de uso específico o un programador aberrante que quiera mostrar que conoce algún rincón oscuro de la programación de Python.

Alex menciona en su respuesta de que el acceso será (un poco) más rápido debido a un nivel menos de búsqueda... permítanme aclarar aún más para aquellos que aún no saben cómo funciona esto, es muy similar al acceso variable the la búsqueda ocurre en este orden:

  1. locales
  2. no locales
  3. globales
  4. built-ins

Para el acceso a atributos, el orden es:

  1. instancia
  2. clase
  3. clases base determinadas por el MRO (method resolution orden)

En tu ejemplo anterior, digamos que estás buscando el atributo path. cuando encuentra una referencia como "self.path", Python buscará primero los atributos de la instancia en busca de una coincidencia; cuando esto falla, comprueba la clase desde la que se creó la instancia del objeto. finalmente, buscará las clases base. como Alex ha dicho, si su atributo se encuentra en la instancia, no se diferirá a la clase, por lo tanto, su poco de ahorro de tiempo.

Sin embargo, si insiste en atributos de clase, tendrá que renunciar a este pequeño poco de rendimiento, o, 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 ese bit que pensabas que ibas a guardar (a menos que crees una referencia local al nombre de la clase [global]).

 41
Author: wescpy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-27 00:45:35

En caso de duda, es probable que desee un atributo de instancia.

Los atributos de clase se reservan mejor para casos especiales donde tienen sentido. El único caso de uso muy común son los métodos. No es rarousar 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 sin duda debe tener cuidado al almacenar cualquier estado en ellos, que rara vez es lo que desea. Incluso si solo tiene una instancia, debe escribir la clase como lo haría con cualquier otra, lo que generalmente significa usar atributos de instancia.

 21
Author: Mike Graham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-26 15:22:14