我正在尝试将一个冗长的空洞"数据"类转换为一个命名元组.我的班级目前看起来像这样:
class Node(object):
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
Run Code Online (Sandbox Code Playgroud)
转换为namedtuple它后看起来像:
from collections import namedtuple
Node = namedtuple('Node', 'val left right')
Run Code Online (Sandbox Code Playgroud)
但这里有一个问题.我的原始类允许我传入一个值,并使用命名/关键字参数的默认值来处理默认值.就像是:
class BinaryTree(object):
def __init__(self, val):
self.root = Node(val)
Run Code Online (Sandbox Code Playgroud)
但是这对我重构的名为元组的情况不起作用,因为它希望我传递所有字段.当然,我可以代替的出现Node(val)到Node(val, None, None),但它不是我的胃口.
所以确实存在着一个很好的技巧,它可以使我重新写成功无需添加大量的代码复杂度(元编程),或者我应该只吞下药丸,并与"查找和替换"继续前进?:)
鉴于我想正确使用类型注释来命名来自打字模块的元组:
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]
Run Code Online (Sandbox Code Playgroud)
避免 Python 中可变默认值痛苦的最佳或最干净的方法是什么?我有一些想法,但似乎没有什么是好的
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)
Run Code Online (Sandbox Code Playgroud)
覆盖__new__或__init__不起作用:
AttributeError: Cannot overwrite NamedTuple attribute __init__
AttributeError: Cannot overwrite NamedTuple attribute __new__
Run Code Online (Sandbox Code Playgroud)
特别的 @classmethod
class Foo(NamedTuple):
my_list: List[int] = []
@classmethod
def use_me_instead(cls, my_list=None):
if not my_list: …Run Code Online (Sandbox Code Playgroud)