2010-04-26 14 views
95

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" Python.Variables de instancia vs. variables de clase en Python

Las variables de clase:

class MyController(Controller): 

    path = "something/" 
    children = [AController, BController] 

    def action(self, request): 
    pass 

Las variables de instancia:

class MyController(Controller): 

    def __init__(self): 
    self.path = "something/" 
    self.children = [AController, BController] 

    def action(self, request): 
    pass 
+4

Después de leer esta pregunta y ver la respuesta, una de mis primeras preguntas fue: "Entonces, ¿cómo puedo acceder a las variables de clase?" - Eso es porque hasta este momento solo he usado variables de instancia. En respuesta a mi propia pregunta, lo haces a través del nombre de la clase en sí, aunque técnicamente puedes hacerlo a través de una instancia también. Aquí hay un enlace para leer para cualquier persona con la misma pregunta: http://stackoverflow.com/a/3434596/4561887 –

Respuesta

138

Si usted tiene sólo una instancia de todas formas, lo mejor es hacer que todas las variables por instancia, simplemente porque se tendrá acceso (una un poco) más rápido (un nivel menos de "búsqueda" debido a la "herencia" de una clase a otra), y no hay inconvenientes que pesen contra esta pequeña ventaja.

+6

¿Nunca escuché sobre el patrón Borg? Solo tener una instancia era la forma incorrecta de tenerla en primer lugar. –

+378

@Devin, sí, he oído hablar del patrón Borg, ya que yo fui el que lo introdujo (en 2001, cfr http://code.activestate.com/recipes/66531-singleton-we-dont-need -no-stinkin-singleton-the-bo/;-). Pero no hay nada malo, en casos simples, simplemente con tener una sola instancia sin aplicación. –

+0

¿Hay puntos de referencia? – user1767754

18

En caso de duda, es probable que 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 infrecuente utilizar atributos de clase para las constantes de solo lectura que las instancias necesitan saber (aunque el único beneficio es si también desea tener acceso desde fuera de la clase), pero debe tener cuidado con el almacenamiento cualquier estado en ellos, que rara vez es lo que quieres. Incluso si solo tiene una instancia, debe escribir la clase como lo haría con cualquier otra, lo que normalmente implica el uso de atributos de instancia.

+0

Las variables de clase son un tipo de constantes de solo lectura. Si Python me dejara definir constantes, lo habría escrito como constantes. – deamon

+1

@deamon, soy ligeramente más propenso a poner mis constantes completamente fuera de las definiciones de una clase y nombrarlas en mayúsculas. Ponerlos dentro de la clase también está bien. Convertirlos en atributos de instancias no dañará nada, pero podría ser un poco extraño. No creo que este sea un problema donde la comunidad se demora demasiado en una de las opciones. –

+0

@MikeGraham FWIW, [Guía de estilo de Python de Google] (http://google-styleguide.googlecode.com/svn/trunk/pyguide.html?showone=Global_variables#Global_variables) sugiere evitar las variables globales a favor de las variables de clase. Sin embargo, hay excepciones. – Dennis

36

eco más asesoramiento Alex de micrófono y de la adición y de mi propio color ...

utilizando atributos de instancia son los Python típica, más idiomática. los atributos de clase no se suelen utilizar, 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 exista un caso de uso específico o un programador aberrante que desee alardear de 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 aún más para aquellos que aún no saben cómo funciona esto, es muy similar al acceso a variables - la búsqueda sucede en este orden:

  1. locales
  2. no locales
  3. globals
  4. empotrados

para acceder atributo, el orden es:

  1. ejemplo
  2. clase
  3. clases base que determine el MRO (método de resolución de orden)

en su ejemplo anterior, digamos que usted' Estamos buscando el atributo path. cuando encuentra una referencia como "self.path", Python examinará primero los atributos de instancia para una coincidencia; cuando eso falla, comprueba la clase desde la que se creó la instancia del objeto.finalmente, buscará las clases base. como ha dicho alex, si su atributo se encuentra en la instancia, no se someterá a la clase, por lo tanto ahorrará un poco de tiempo. Sin embargo

, si insiste en atributos de clase, tendrá que renunciar a esta pequeña gota de rendimiento, o, la otra alternativa es hacer referencia al objeto a través de la clase en lugar de la instancia, por ejemplo, MyController.path vez de self.path. esa es una búsqueda directa que sorteará la búsqueda diferida, pero como menciona Alex a continuación, esa 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])

+0

@wescpy, pero 'MyController' se busca en los globales, por lo que el costo total es mayor que' self.path' donde 'path' es una variable de instancia (ya que' self' es _local_ al método == super-rápido buscar). –

+0

ah, cierto. buena atrapada. Supongo que la única solución es crear una referencia local ... en este punto, realmente no vale la pena. – wescpy

Cuestiones relacionadas