python 如何知道 dataclasses.field 函数不是数据类中的默认值?

How does python know that dataclasses.field function is not a default value in a dataclass?

考虑以下 class:

from dataclasses import dataclass

@dataclass
class C:
  a: int = 1
  b: int

尝试执行此操作会产生 TypeError: non-default argument 'b' follows default argument

现在考虑一下:

from dataclasses import dataclass, field
from dataclasses_json import config

@dataclass
class C:
  a: int = field(metadata=config(encoder=lambda x: x, decoder=lambda x: x))
  b: int

这执行没有错误。

问题是:field 函数如何“欺骗”python 解释器而不被视为默认值?我可以在我自己的函数中复制这种行为吗?

@dataclass 不是“由解释器解释”,因为解释器不“知道”它必须引发像 TypeError: non-default argument 'b' follows default argument 这样的错误。相反,@dataclass 是检查 class 对象和 explicitly raises the error.

的常规 Python 函数

这种机制的高级描述是 field returns a Field object containing the meta-data passed to field. The @dataclass code checks if class attribute values are Field objects,而不是它们是否由 field 创建 – 如果需要,可以编写自定义函数来构造 Field 实例.
当然,最简单的方法就是调用 field 的函数来创建 Field.

from dataclasses import field, MISSING


def auto_field(*, default=MISSING, default_factory=MISSING, init=True, metadata=None):
    """Field that inspects defaults to decide whether it is repr/hash'able"""
    if default is MISSING and default_factory is MISSING:
        return field(init=init, metadata=metadata)
    test_default = default if default is not MISSING else default_factory()
    return field(
        default=default, default_factory=default_factory, init=init, metadata=metadata,
        repr=type(test_default).__repr__ is not object.__repr__,
        hash=getattr(test_default, '__hash__', None) is not None,
        compare=getattr(test_default, '__hash__', None) is not None,
    )
from dataclasses import dataclass

@dataclass(frozen=True)
class Foo:
    a: int = auto_field()  # not counted as a default
    b: int
    c: list = auto_field(default_factory=list)


print(Foo(12, 42), hash(Foo(12, 42)))  # works because c is ignored for hashing

请注意,从概念上讲,人们仍然受限于 dataclass 及其 Field 的逻辑。例如,这意味着不能创建“ 具有默认值 但不被视为默认值的字段”——根据处理方式,dataclass 要么忽略它或者在准备实际的 class.

时仍然会引发错误