Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用字典默认值键入.NamedTuple_Python_Namedtuple - Fatal编程技术网

Python 使用字典默认值键入.NamedTuple

Python 使用字典默认值键入.NamedTuple,python,namedtuple,Python,Namedtuple,我试图创建一个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.

我试图创建一个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
如何确保每个实例的
字段都是新的dict?中的所有dicts示例似乎都使用ClassVar,但这与我想要的正好相反

我可以在这里使用带有(或attrs中的等效项)的dataclass,但我目前需要支持python 3.6.x和3.7.x,因此这会增加一些开销


值得一提的是,我正在测试的python版本是3.7.3,键入。NamedTuple/
集合。NamedTuple
不支持工厂函数,实现默认值的机制看起来也不以任何合理的方式重载。您也不能通过直接编写自己的
\uuuu new\uuu
来手动实现这种默认设置

在AICT中,唯一半合理的方法是编写一个名为tuple的
的子类,它实现自己的
\uuuu new\uuuu
,以编程方式生成默认值:

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
继承一样。这不应该对性能产生有意义的影响,只是需要注意