1

我正在编写这段小代码作为面向对象编程的练习。

在这里,我试图将房屋定义为房间列表,并将每个房间定义为设备列表(例如灯)。

首先,我创建了所有对象,它们将两个房间附加到房子上,并将不同的设备附加到每个房间。很基本。

问题是该设备似乎被附加到两个房间。这是为什么?

编码:

#! /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()

和输出。

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>

请注意,d1 的同一个实例在两个房间 r1 和 r2 中。

4

3 回答 3

9

函数的默认参数值仅计算一次。这意味着 House 的所有实例都将使用相同的列表实例self.rooms(如果在构造中未给出房间参数)。以同样的方式,Room 的所有实例将共享相同的列表self.devs

为了解决这个问题,编写如下代码:

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

其他班级也是如此。

于 2009-12-07T15:39:38.387 回答
3

默认参数在方法的声明点被评估一次。然后在对该方法的所有调用中使用该值。

在 stackoverflow 上还有其他问题,探讨了这种设计的原因以及如何最好地避免这些可变的默认参数

于 2009-12-07T15:50:05.277 回答
0
def __init__(self, name = 'a room', devs = list()):
    self.name = name
    self.devs = devs
    print('room ' + self.name + ' created')

当你这样做时,list()实际上总是相同的列表。每次调用构造函数时都不会得到一个新的空列表,而是得到相同的空列表。要解决这个问题,您需要制作一份副本。

list()更习惯地写为[].

def __init__(self, name='a room', devs=[]):
    self.name = name
    self.devs = list(devs)
    print('room ' + self.name + ' created')
于 2009-12-07T15:46:46.097 回答