我遇到了一个简单的方法,让命名元组使用来自here的默认参数。
from collections import namedtuple
Node = namedtuple('Node', 'val left right')
Node.__new__.__defaults__ = (None, None, None)
Node()
节点(val =无,左=无,右=无)
如果您希望“正确”的默认值为空列表,您会怎么做?您可能知道,使用可变默认参数(例如列表)是否定的。
有没有一种简单的方法来实现它?
答案 0 :(得分:5)
你不能这样做,因为__defaults__
中的值是实际的默认值。也就是说,如果您编写了一个具有someargument=None
的函数,然后使用someargument = [] if someargument is None else someargument
等在函数体内部进行了检查,则相应的__defaults__
条目仍然是None。换句话说,您可以使用函数执行此操作,因为在函数中您可以编写代码来执行任何操作,但是您无法在命名元组内编写自定义代码。
但是如果你想要默认值,只需创建一个具有该逻辑的函数,然后创建正确的命名元组:
def makeNode(val=None, left=None, right=None):
if right is None:
val = []
return Node(val, left, right)
答案 1 :(得分:1)
the accepted answer中给出的方式很有效。我看到的唯一缺点是,一个人必须知道(在某些其他用户的情况下)和记住以使用工厂函数而不是命名的元组类 - 两者都是在创建对象时,以及在做这样的事情时:
isinstance(node, Node) # success
isinstance(node, makeNode) # misery
解决此问题的方法可能是执行如下所示的操作。
NodeBase = nt('NodeBase', 'val left right')
NodeBase.__new__.__defaults__ = (None, None, None)
class Node(NodeBase):
'''A namedtuple defined as:
Node(val, left, right)
with default values of (None, None, [])'''
__slots__ = ()
def __new__(cls, *args, **kwargs):
obj = super().__new__(cls, *args, **kwargs)
if obj.right is None:
obj = obj._replace(right = [])
return obj
答案 2 :(得分:0)
与Rick Teachey相比,实现上的改动很小,可以在类外部设置默认值:
NodeBase = namedtuple('NodeBase', 'val left right')
class Node(NodeBase):
__slots__ = ()
def __new__(cls, *, right=[], **kwargs):
obj = super().__new__(cls, right=[], **kwargs)
return obj
#IMPLEMENTATION
kw = {'val': 1, 'left':12}
m = Node(**kw)
# outputs Node(val=1, left=12, right=[])