Python 3.9中namedtuple的_field_defaults异常行为解析求助
关于namedtuple中
_field_defaults的两个常见问题解释 问题1:直接修改类的_field_defaults后调用无参构造报错
直接修改Person._field_defaults的方式无效,因为namedtuple的构造函数签名是在类创建时就固定的。当你用namedtuple('Person', 'name age')定义类时,生成的构造函数(底层是lambda)要求必须传入name和age两个参数,没有默认值。
_field_defaults只是类的一个元数据属性,用来存储默认值信息,但它不会动态修改构造函数的参数规则。所以即使你给_field_defaults添加了键值对,构造函数依然会要求传入所有必填参数,触发TypeError。
正确做法是在创建namedtuple时通过defaults参数指定默认值:
from collections import namedtuple # 创建时直接指定默认值,构造函数会自动生成带默认参数的签名 Person = namedtuple('Person', 'name age', defaults=['John', 30]) person1 = Person() # 正常运行 person2 = Person(name='Alice') # 正常运行 print(person1) # Person(name='John', age=30) print(person2) # Person(name='Alice', age=30)
问题2:修改实例的_field_defaults不影响新实例
首先明确:_field_defaults是类级别的属性,实例的p._field_defaults本质是引用类的Person._field_defaults字典。但修改后新实例默认值不变的原因是:
namedtuple的构造函数在创建类时,已经把默认参数的值绑定到了函数定义中,后续修改_field_defaults字典不会同步更新构造函数的默认参数。简单说,构造函数用的是创建类时的默认值快照,而非动态读取_field_defaults的内容。
即使直接修改类的Person._field_defaults,新实例依然会使用原来的默认值。如果需要动态更新默认值,建议改用dataclasses.dataclass(Python 3.7+),它支持动态修改类的默认值:
from dataclasses import dataclass @dataclass class Person: name: str = 'default_name' age: int = 0 # 动态修改类的默认值 Person.age = 100 p = Person() print(p) # Person(name='default_name', age=100)
内容的提问来源于stack exchange,提问作者Ku Zijie
相关产品推荐
相关产品推荐

