今天遇到了一个没想通的问题,先记录下来。
函数传参
def add_bar(items=[]):
# print(items)
items.append('bar')
return items
a = add_bar([])
print('a:',a)
b = add_bar([])
print('a:',a,'\t b:',b)
print('b:',b,'\t f:',add_bar())
print(id(a),id(b))
# return
# a: ['bar']
# a: ['bar'] b: ['bar']
# b: ['bar'] f: ['bar']
# 1112207291464 112207598152
如上所示,是没有任何问题的。但是当我把代码改成下面形式时(我所做的只是去掉传递的参数,空列表 '[]' ),便会出现不可思议的事情:
def add_bar(items=[]):
# print(items)
items.append('bar')
return items
a = add_bar()
print('a:',a)
b = add_bar()
print('a:',a,'\t b:',b)
print('b:',b,'\t f:',add_bar())
print(id(a),id(b))
# return
# a: ['bar']
# a: ['bar', 'bar'] b: ['bar', 'bar']
# b: ['bar', 'bar', 'bar'] f: ['bar', 'bar', 'bar']
# 112025071816 112025071816
当我没有传递参数时,可以看到 id(a) 是等于 id(b) 的。这表明默认参数已经修改了,不再是 '[]'。我看到有的文章给出建议,说当参数使用字典、集合和列表时,在默认参数位置填‘None',而不是 ’[]' 或者 '{}' 等。
有些时候列表和元组可以互换使用,因此人们经常会在代码中随机使用两者之一。于是当你试图修改一个元组(比如给其中一个元素赋值)时就会出错。或者试图用列表作为字典的键,也会导致 TypeError,因为列表是可修改的。元组和字符串可以作为字典的键使用,因为它们不可修改,可以得到确定的哈希值,而其他数据结构都不行,因为它们的对象标识即使保持不变,值也会改变。
函数设置参数时,在默认参数的位置使用元组或 None(代替空字典或空列表),并且在缺乏足够的防御代码的情况下,避免将可修改的数据结构在不同的上下文中传递。
——— 在 Python 中使用函数式编程的最佳实践
类参数
如下所示定义参数的话,则会出现一个类下面的多个实例,共用同一个参数的问题(bus1 和 bus2 的 passeners 相同):
class Bus(object):
passengers = set()
def add_passenger(self, person):
self.passengers.add(person)
bus1 = Bus()
bus2 = Bus()
bus1.add_passenger('abe')
bus2.add_passenger('bertha')
print(bus1.passengers, bus2.passengers)
print(id(bus1.passengers), id(bus2.passengers))
# return
# {'bertha', 'abe'} {'bertha', 'abe'}
# 112108429608 112108429608
当然如果改成如下形式,就会消除该问题:
class Bus(object):
def __init__(self):
self.passengers = set()
def add_passenger(self, person):
self.passengers.add(person)
bus1 = Bus()
bus2 = Bus()
bus1.add_passenger('abe')
bus2.add_passenger('bertha')
print(bus1.passengers,bus2.passengers)
print(id(bus1.passengers),id(bus2.passengers))
# return
# {'abe'} {'bertha'}
# 111998300456 111998302472
先写这些吧~ 感觉还是半懂不懂,不过暂时先记住结论,以后传递参数的时候,一定要长一个心眼~
网友评论