本文共 1070 字,大约阅读时间需要 3 分钟。
如果参数的实际默认值是可变类型(mutable),那就一定要记得用 None 作为形式上的默认值。例如,从编码为 JSON 格式的数据中载入某个值。若解码数据时失败,则默认返回空的字典。我们可能会采用下面这种办法来实现此功能:
import jsondef decode(data,default = {}): try: json.loads(data) except ValueError: return defaultfoo = decode('bad data')foo['stuff'] = 'why'bar = decode('also bad')bar['meep'] = 'i dunno' print('Foo',foo) print('Bar',bar)
由于 default 参数的默认值只会在模块加载时评估一次,所以凡是以默认形式来调用 decode 函数的代码,都将共享同一份字典。
输出结果:('Foo', {'stuff': 'why', 'meep': 'i dunno'})('Bar', {'stuff': 'why', 'meep': 'i dunno'})
我们本以为 foo 和 bar 会表示两份不同的字典,每个字典里都有一对键和值,但实际上,修改了其中一个之后,另外一个似乎也会受到影响。这种错误的根本原因是:foo 和 bar 其实都等同于写在 default 参数默认值中的那个字典,它们都表示的是同一个字典对象。
解决办法,是把关键字参数的默认值设为 None,并在函数的文档字符串中描述它的实际行为。
def decode(data,default = None): if default is None: default = {} try: json.loads(data) except ValueError: return default现在,再来运行和刚才相同的测试代码,就能产生符合预期的结果了。
('Foo', {'stuff': 'why'})('Bar', {'meep': 'i dunno'})
参数的默认值,只会在程序加载模块并读到本函数的定义时评估一次。对于 {} 或 [ ] 等动态的值,这可能会导致奇怪的行为。
对于以动态值作为实际默认值的关键字参数来说,应该把形式上的默认值写为None,并在函数的文档字符串里面描述该默认值所对应的实际行为。
转载地址:http://affob.baihongyu.com/