¿Por qué las nuevas instancias de una clase comparten miembros con otras instancias?

StackOverflow https://stackoverflow.com/questions/307729

  •  08-07-2019
  •  | 
  •  

Pregunta

class Ball:
  a = []
  def __init__(self):
    pass

  def add(self,thing):
    self.a.append(thing)

  def size(self):
    print len(self.a)

for i in range(3):
  foo = Ball()
  foo.add(1)
  foo.add(2)
  foo.size()

Esperaría un retorno de:

2
2
2

Pero obtengo:

2
4
6

¿Por qué es esto? Descubrí que haciendo un = [] en el init , puedo enrutar este comportamiento, pero no estoy muy claro por qué.

¿Fue útil?

Solución

doh

Acabo de descubrir por qué.

En el caso anterior, a es un atributo de clase, no un atributo de datos; todos los Balls comparten estos. Al comentar a = [] y colocarlo en el bloque init significa que es un atributo de datos. (Y no pude acceder a él con foo.a, lo cual no debería hacer de todos modos). Parece que los atributos de clase actúan como atributos estáticos de la clase, son compartidos por todas las instancias.

Whoa.

Sin embargo, una pregunta: CodeCompletion apesta así. En la clase foo, no puedo hacer self (variable), porque no se define automáticamente, sino que se define mediante una función. ¿Puedo definir una variable de clase y reemplazarla con una variable de datos?

Otros consejos

Lo que probablemente quieras hacer es:

class Ball:
  def __init__(self):
    self.a = []

Si usa solo a = [] , crea una variable local en la función __init__ , que desaparece cuando la función regresa. Asignar a self.a lo convierte en una variable de instancia que es lo que buscas.

Para un problema semi relacionado, vea cómo puede cambiar el valor de los parámetros predeterminados para futuras llamadas .

" ¿Puedo definir una variable de clase y reemplazarla con una variable de datos? "

No. Son cosas separadas. Una variable de clase existe precisamente una vez, en la clase.

Podría, para completar el código, comenzar con algunas variables de clase y luego eliminar esas líneas de código después de haber escrito su clase. Pero cada vez que te olvides de hacer eso, nada bueno sucederá.

Mejor es probar un IDE diferente. Komodo Edit terminaciones de código parece ser sensato.

Si tiene tantas variables con nombres tan largos que la finalización del código es realmente útil, quizás debería hacer que sus clases sean más pequeñas o usar nombres más cortos. Seriamente.

Me parece que cuando llegas a un lugar donde completar el código es más útil que molesto, has excedido el "mantenerlo todo en mi cerebro". umbral de complejidad Si la clase no cabe en mi cerebro, es demasiado compleja.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top