如何确定dataclass中的字段是否具有默认值或是否显式设置?

2024-10-01 00:19:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个dataclass,我想知道每个字段是显式设置的还是由default或{}填充的。在

我知道我可以使用dataclasses.fields(...)获得所有字段,这可能适用于使用default的字段,但对于使用default_factory的字段,这可能不容易。在

我的最终目标是合并两个dataclass实例AB。而B应该只覆盖A的字段,其中A使用默认值。在

用例是一个可以在多个位置指定的配置对象,其中一些具有比其他位置更高的优先级。在

编辑:一个例子

from dataclasses import dataclass, field

def bar():
  return "bar"

@dataclass
class Configuration:
  foo: str = field(default_factory=bar)

conf1 = Configuration(
)

conf2 = Configuration(
  foo="foo"
)

conf3 = Configuration(
  foo="bar"
)

我想检测conf1.foo正在使用默认值,并且conf2.foo&;conf3.foo是显式设置的。在


Tags: 对象实例defaultfieldfieldsfoofactorybar
1条回答
网友
1楼 · 发布于 2024-10-01 00:19:45

首先,考虑到你对fields的了解,像这样的merge函数可能就是您可以编写的,而实例{}则显示了它的缺点。但是考虑到这个实现完全按照预期的方式使用dataclass工具,这意味着它相当稳定,所以如果可能的话,您应该使用这个:

from dataclasses import asdict, dataclass, field, fields, MISSING


@dataclass
class A:
    a: str
    b: float = 5
    c: list = field(default_factory=list)


def merge(base, add_on):
    retain = {}
    for f in fields(base):
        val = getattr(base, f.name)
        if val == f.default:
            continue
        if f.default_factory != MISSING:
            if val == f.default_factory():
                continue
        retain[f.name] = val
    kwargs = {**asdict(add_on), **retain}
    return type(base)(**kwargs)


fill = A('1', 1, [1])

x = A('a')
y = A('a', 2, [3])
z = A('a', 5, [])
print(merge(x, fill))  # good: A(a='a', b=1, c=[1])
print(merge(y, fill))  # good: A(a='a', b=2, c=[3])
print(merge(z, fill))  # bad:  A(a='a', b=1, c=[1])

正确处理z案例涉及到某种的黑客攻击,我个人会再次装饰dataclass:

^{pr2}$

这很可能有一些难以猜测的副作用,所以使用风险自负。在

相关问题 更多 >