¿Qué estoy haciendo mal? ¿La creación de instancias de objetos de Python conserva los datos de la instanciación anterior?

¿Puede alguien señalarme qué estoy haciendo mal o dónde está mal mi entendimiento?

Para mí, me parece que el código debajo del cual se crea una instancia de dos objetos debería tener datos separados para cada instanciación.

class Node: def __init__(self, data = []): self.data = data def main(): a = Node() a.data.append('a-data') #only append data to the a instance b = Node() #shouldn't this be empty? #a data is as expected print('number of items in a:', len(a.data)) for item in a.data: print(item) #b data includes the data from a print('number of items in b:', len(b.data)) for item in b.data: print(item) if __name__ == '__main__': main() 

Sin embargo, el segundo objeto se crea con los datos del primero:

 >>> number of items in a: 1 a-data number of items in b: 1 a-data 

    No puede utilizar un objeto mutable como valor predeterminado. Todos los objetos compartirán el mismo objeto mutable.

    Hacer esto.

     class Node: def __init__(self, data = None): self.data = data if data is not None else [] 

    Cuando crea la definición de clase, crea el objeto de lista [] . Cada vez que creas una instancia de la clase, usa el mismo objeto de lista como valor predeterminado.

    El problema está en esta línea:

     def __init__(self, data = []): 

    Cuando escribe data = [] para establecer una lista vacía como el valor predeterminado para ese argumento, Python solo crea una lista una vez y usa la misma lista cada vez que se llama al método sin un argumento de data explícito. En su caso, eso sucede en la creación de a y b , ya que no le da una lista explícita a ninguno de los constructores, por lo que a y b están usando el mismo objeto que su lista de data . Cualquier cambio que hagas en uno se reflejará en el otro.

    Para solucionar esto, sugeriría reemplazar la primera línea del constructor con

     def __init__(self, data=None): if data is None: data = [] 

    Cuando proporciona valores predeterminados para una función o método, generalmente desea proporcionar objetos inmutables. Si proporciona una lista vacía o un diccionario vacío, terminará con todas las llamadas a esa función o método que comparte el objeto.

    Una buena solución es:

     def __init__(self, data = None): if data == None: self.data = [] else: self.data = data