Dell'oggetto aggiunto a un'istanza elenco viene visualizzato in una diversa istanza di tale elenco

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

Domanda

stavo scrivendo questo piccolo pezzo di codice come un esercizio di programmazione orientata agli oggetti.

Qui sto cercando di definire una casa come una lista di camere e ogni camera come una lista di dispositivi (lampade, per esempio).

Per prima cosa ho creato tutti gli oggetti e le allegate le due stanze alla casa e un dispositivo diverso per ogni stanza. Piuttosto semplice.

Il problema è che sembra che il dispositivo viene aggiunto ad entrambe le camere. Perché?

Il codice:

#! /usr/bin/python

class House:
        def __init__(self, rooms = list()):
                self.rooms = rooms
                print('house created')


class Room:
        def __init__(self, name = 'a room', devs = list()):
            self.name = name
            self.devs = devs
            print('room ' + self.name + ' created')


class Device:
        def __init__(self, name = 'a device'):
                self.name = name
                print('device ' + self.name + ' created')


def main():
        #1
        h = House()
        r1 = Room(name = 'R1')
        r2 = Room(name = 'R2')
        d1 = Device(name = 'lamp1')
        d2 = Device(name = 'lamp2')

        #2
        h.rooms.append(r1)
        h.rooms.append(r2)

        for room in  h.rooms:
                print room.name

        print h.rooms[0]
        print h.rooms[1]
        h.rooms[1].devs.append(d1)

        #3
        for room in h.rooms:
                print room.name
                for dev in room.devs:
                        print('room ' + room.name + ' > ' + dev.name)
                        print room
                        print dev


if __name__ == '__main__' : main()

E l'uscita.

house created
room R1 created
room R2 created
device lamp1 created
device lamp2 created
R1
R2
<__main__.Room instance at 0xb7d8a58c>
<__main__.Room instance at 0xb7d8a5ac>
R1
room R1 > lamp1
<__main__.Room instance at 0xb7d8a58c>
<__main__.Device instance at 0xb7d8a5cc>
R2
room R2 > lamp1
<__main__.Room instance at 0xb7d8a5ac>
<__main__.Device instance at 0xb7d8a5cc>

Si noti che la stessa istanza di d1 è in entrambe le camere, R1 e R2.

È stato utile?

Soluzione

i valori dei parametri predefiniti per le funzioni vengono calcolate una sola volta. Ciò significa che tutte le istanze di Casa utilizzeranno la stessa istanza lista per self.rooms (se il parametro camere non è stato dato nelle costruzioni). Allo stesso modo, tutte le istanze di camera condivideranno la stessa lista per self.devs.

Per risolvere questo problema, scrivere il codice in questo modo:

def __init__(self, rooms = None):
    if rooms is None:
        rooms = []
    self.rooms = rooms
    print('house created')

E la stessa cosa per le altre classi.

Altri suggerimenti

L'argomento predefinito viene valutata una volta, nel punto di dichiarazione del metodo. Tale valore viene quindi utilizzato in tutte le chiamate al metodo.

Ci sono altre domande su StackOverflow esplorare le ragioni di questo disegno e come meglio evitare questi argomenti di default mutevoli .

def __init__(self, name = 'a room', devs = list()):
    self.name = name
    self.devs = devs
    print('room ' + self.name + ' created')

Quando si esegue questa list() in realtà è sempre la stessa lista. Non si ottiene un nuovo elenco vuoto ogni volta che il costruttore viene chiamato, si ottiene il stesso lista vuota. Per risolvere che si vorrà fare una copia.

Anche list() è più idiomaticamente scritto come [].

def __init__(self, name='a room', devs=[]):
    self.name = name
    self.devs = list(devs)
    print('room ' + self.name + ' created')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top