Typing.NamedTuple和可变默认参数

鉴于我想正确使用类型注释来命名来自打字模块的元组:

from typing import NamedTuple, List

class Foo(NamedTuple):
    my_list: List[int] = []

foo1 = Foo()
foo1.my_list.append(42)

foo2 = Foo()
print(foo2.my_list)  # prints [42]

避免 Python 中可变默认值痛苦的最佳或最干净的方法是什么?我有一些想法,但似乎没有什么是好的

  1. None默认使用

    class Foo(NamedTuple):
        my_list: Optional[List[int]] = None
    
    foo1 = Foo()
    if foo1.my_list is None
      foo1 = foo1._replace(my_list=[])  # super ugly
    foo1.my_list.append(42)
    
  2. 覆盖__new____init__不起作用:

    AttributeError: Cannot overwrite NamedTuple attribute __init__
    AttributeError: Cannot overwrite NamedTuple attribute __new__
    
  3. 特别的 @classmethod

    class Foo(NamedTuple):
        my_list: List[int] = []
    
        @classmethod
        def use_me_instead(cls, my_list=None):
           if not my_list:
               my_list = []
           return cls(my_list)
    
    foo1 = Foo.use_me_instead()
    foo1.my_list.append(42)  # works!
    
  4. 也许frozenset完全使用和避免可变属性?但这不适用于Dicts,因为没有frozendicts。

有人有好的答案吗?

回答

使用数据类而不是命名元组。数据类允许字段指定默认工厂而不是单个默认值。

from dataclasses import dataclass, field


@dataclass(frozen=True)
class Foo:
    my_list: List[int] = field(default_factory=list)


以上是Typing.NamedTuple和可变默认参数的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>