用 None 和文档字符串来描述具有动态默认值的参数

本文探讨了Python函数默认参数使用不当可能导致的问题,特别是当默认参数为可变类型时,多个调用间可能出现意料之外的数据共享。文章提供了一个简单有效的解决方案,并通过示例展示了正确做法。

     如果参数的实际默认值是可变类型(mutable),那就一定要记得用 None 作为形式上的默认值。例如,从编码为 JSON 格式的数据中载入某个值。若解码数据时失败,则默认返回空的字典。我们可能会采用下面这种办法来实现此功能:

import json

def decode(data,default = {}):  
    try:
        json.loads(data)
    except ValueError:
        return default

foo = 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,并在函数的文档字符串里面描述该默认值所对应的实际行为。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值