如何在数据类中使用field()?

Chr*_*ein 10 python python-dataclasses

我经常看到这样的代码:

@dataclass
class ClassName:
    list_name: list[int] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)

但我不明白为什么我需要输入field(default_factory=list). 还不够吗list_name: list[int]

您能解释一下何时、为什么以及如何在数据类中使用 field() 吗?

jua*_*aga 15

正在做:

list_name: list[int]
Run Code Online (Sandbox Code Playgroud)

不等于:

list_name: list[int] = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)

后者使用 a default_factory,所以注意:

>>> from dataclasses import dataclass
>>> @dataclass
... class ClassName:
...     list_name: list[int]
...
>>> ClassName()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() missing 1 required positional argument: 'list_name'
Run Code Online (Sandbox Code Playgroud)

但如果你使用默认工厂:

>>> @dataclass
... class ClassName:
...     list_name: list[int] = field(default_factory=list)
...
>>> ClassName()
ClassName(list_name=[])
Run Code Online (Sandbox Code Playgroud)

请注意,如果您这样做list_name: list[int] = [],那么它将为每个实例重复使用相同的list对象,几乎肯定不是您想要的。事实上,dataclass装饰器明确拒绝了这一点:

>>> @dataclass
... class ClassName:
...     list_name: list[int] = []
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Users/juanarrivillaga/opt/miniconda3/envs/py39/lib/python3.9/dataclasses.py", line 1021, in dataclass
    return wrap(cls)
  File "/Users/juanarrivillaga/opt/miniconda3/envs/py39/lib/python3.9/dataclasses.py", line 1013, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
  File "/Users/juanarrivillaga/opt/miniconda3/envs/py39/lib/python3.9/dataclasses.py", line 863, in _process_class
    cls_fields = [_get_field(cls, name, type)
  File "/Users/juanarrivillaga/opt/miniconda3/envs/py39/lib/python3.9/dataclasses.py", line 863, in <listcomp>
    cls_fields = [_get_field(cls, name, type)
  File "/Users/juanarrivillaga/opt/miniconda3/envs/py39/lib/python3.9/dataclasses.py", line 747, in _get_field
    raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field list_name is not allowed: use default_factory
Run Code Online (Sandbox Code Playgroud)

一般来说,dataclasses.field当您需要修改各个字段时,您可以显式地使用 a 。