我在Bug中写Python系列(不要使用可变类型作为参数的默认值)(1ni)

# *_*coding:utf-8 *_*

class Bus:

    """
        这样给默认值参数的话
        bus1=Bus(passengers)
        bus4=Bus(passengers)

        bus2=Bus()
        bus3=Bus()

        其中 bus1和bus4指代同一个列表
             bus2和bus3指代同一个列表
             
        但是 bus5,bus6就不会
    """
    def __init__(self, passengers=[]):
        self.passengers = passengers

    def pick(self, name):
        self.passengers.append(name)

    def drop(self, name):
        self.passengers.remove(name)

    def __repr__(self):
        return ', '.join(self.passengers)

passengers = ['Alice','Bill']
bus1 = Bus(passengers)
print(bus1.passengers)
bus1.pick('Bob')
bus1.drop('Alice')
print(bus1.passengers)

bus2 = Bus()
bus2.pick('A')
print(bus2.passengers)

bus3 = Bus()
print(bus3.passengers)

bus3.pick('B')
print(bus3.passengers is bus2.passengers)

bus4 = Bus(passengers)
print(bus4.passengers)

bus5 = Bus(['AA','BB'])
bus5.pick('CC')
bus6 = Bus(['AA','BB'])
print(bus5.passengers)
print(bus6.passengers)

这种问题很难发现。如示例 8-13 所示,实例化 Bus时,如果传入乘客,会按预期运作。但是不为 Bus指定乘客的话,奇怪的事就发生了,这是因为 self.passengers 变成了 passengers 参数默认值的别名。出现这个问题的根源是,默认值在定义函数时计算(通常在加载模块时),因此默认值变成了函数对象的属性。因此,如果默认值是可变对象,而且修改了它的值,那么后续的函数调用都会受到影响。----------参考《流畅的Python》


所以我们应该这样修改

# *_*coding:utf-8 *_*

class Bus:

    def __init__(self,passengers=None):
        if passengers is None:
            self.passengers = []
        else:
            self.passengers = list(passengers) # list(passengers)实际上是把参数的副本传进去

    def pick(self,name):
        self.passengers.append(name)

    def drop(self,name):
        self.passengers.remove(name)

    def __repr__(self):
        return ', '.join(self.passengers)


猜你喜欢

转载自blog.csdn.net/qq_40952927/article/details/80469874
今日推荐