gpt4 book ai didi

python - 如何确定数据类中的字段是否具有默认值或是否已显式设置?

转载 作者:行者123 更新时间:2023-12-01 07:46:37 24 4
gpt4 key购买 nike

我有一个dataclass,我想查明每个字段是否已显式设置,或者是否由defaultdefault_factory< 填充.

我知道我可以使用 dataclasses.fields(...) 获取所有字段,这可能适用于使用 default 的字段,但对于使用 default 的字段则不然使用default_factory

我的最终目标是合并两个数据类实例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.fooconf3.foo 已显式设置.

最佳答案

首先,考虑到您对字段的了解,您可能可以编写类似merge函数的内容,以实例z为例> 显示其缺点。但鉴于此实现完全按照其预期方式使用 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 案例将涉及某种类型的黑客攻击,我个人只是再次装饰数据类:

from dataclasses import asdict, dataclass, field, fields


def mergeable(inst):
old_init = inst.__init__

def new_init(self, *args, **kwargs):
self.__customs = {f.name for f, _ in zip(fields(self), args)}
self.__customs |= kwargs.keys()
old_init(self, *args, **kwargs)

def merge(self, other):
retain = {n: v for n, v in asdict(self).items() if n in self.__customs}
kwargs = {**asdict(other), **retain}
return type(self)(**kwargs)

inst.__init__ = new_init
inst.merge = merge
return inst


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


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

x = A('a')
y = A('a', 2, [3])
z = A('a', 5, [])

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

但这很可能会产生一些难以猜测的副作用,因此使用时需要您自担风险。

关于python - 如何确定数据类中的字段是否具有默认值或是否已显式设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56430869/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com