gpt4 book ai didi

python - 具有字典默认值的typing.NamedTuple

转载 作者:行者123 更新时间:2023-12-01 06:46:17 26 4
gpt4 key购买 nike

我正在尝试创建一个 NamedTuple,其中一个字段默认为空字典。这大部分都有效,但是默认值在 NamedTuple 的实例之间共享:

from typing import NamedTuple, Dict

class MyTuple(NamedTuple):
foo: int
bar: Dict[str, str] = {}


t1 = MyTuple(1, {})
t2 = MyTuple(2)
t3 = MyTuple(3)

t2.bar["test2"] = "t2"
t3.bar["test3"] = "t3"

print(t2) # MyTuple(foo=2, bar={'test2': 't2', 'test3': 't3'})
print(t3) # MyTuple(foo=3, bar={'test2': 't2', 'test3': 't3'})
assert "test3" not in t2.bar # raises

如何确保 bar 字段是每个实例的新字典? PEP-526 中的所有字典示例似乎使用 ClassVar,但这与我想要的相反。

我可能会在此处使用带有 default factory function 的数据类(或 attrs 中的等效项),但我目前需要支持 python 3.6.x 和 3.7.x,因此这会增加一些开销。

就其值(value)而言,我测试的 python 版本是 3.7.3

最佳答案

typing.NamedTuple/collections.namedtuple 不支持工厂函数,并且实现默认值的机制看起来不能以任何合理的方式重载。您也不能通过直接编写自己的 __new__ 来手动实现这样的默认值。

AFAICT,唯一半合理的方法是编写一个 namedtuple 的子类,该子类实现自己的 __new__ 以编程方式生成默认值:

class MyTuple(NamedTuple):
foo: int
bar: Dict[str, str] = {} # You can continue to declare the default, even though you never use it

class MyTuple(MyTuple):
__slots__ = ()
def __new__(cls, foo, bar=None):
if bar is None:
bar = {}
return super().__new__(cls, foo, bar)

开销相对较小,但确实涉及六行样板文件。您可以减少样板文件(以可能过于密集的代码为代价)将父 MyTuple 的定义一行一行地添加到最终 MyTuple 的定义中,以减少冗长,例如:

class MyTuple(typing.NamedTuple('MyTuple', [('foo', int), ('bar', Dict[str, str])])):
__slots__ = ()
def __new__(cls, foo, bar=None):
if bar is None:
bar = {}
return super().__new__(cls, foo, bar)

但这仍然会形成一个继承层次结构,而不仅仅是像从 NamedTuple 中“继承”那样的 tuple 类的单个直接后代。这不会对性能产生有意义的影响,只是需要注意的事情。

关于python - 具有字典默认值的typing.NamedTuple,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59205528/

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