Python函数默认字典参数复用历史值 未按预期初始化问题
根本原因
该现象和Flask框架无关,是Python语言本身的函数默认参数求值规则导致的:
- Python函数的默认参数在函数定义阶段就会完成求值、创建对应对象,而非每次调用函数时临时生成
- 所有未传入对应参数的函数调用,都会复用同一个默认参数对象的引用
你的代码中把可变类型dict(空字典{})设为默认参数,首次调用时adapt_charge逻辑修改了这个字典对象本身,后续不传charge的调用拿到的都是已经被修改过的同一个字典对象,就会出现残留上一次调用数据的问题。除了字典之外,列表、自定义类实例等可变类型作为默认参数时都会出现同类问题。
可以用极简代码复现该行为:
def test_func(param: dict = {}): param["count"] = param.get("count", 0) + 1 print(param) test_func() # 输出 {'count': 1} test_func() # 输出 {'count': 2} test_func() # 输出 {'count': 3}
无需deepcopy的解决方案
遵循Python编码规范,不要使用可变类型作为函数默认参数,用不可变值None作为默认占位符,在函数内部判断参数为None时再初始化新的空字典即可,修改后的代码如下:
def get_charge(move: dict, charge: dict = None) -> dict: if charge is None: charge = {} charge = adapt_charge(move, charge) return charge
该写法下,每次未传入charge参数调用函数时,都会在函数内部新建一个独立的空字典对象,不同调用之间的数据完全隔离,不会出现互相污染的问题,性能远高于使用deepcopy的临时方案。
你之前用deepcopy的方案本质是每次复制复用的默认参数对象来规避污染,属于冗余操作,没有从根源上适配Python的语法特性。
内容的提问来源于stack exchange,提问作者yassine khelifa
相关产品推荐
相关产品推荐

