Python namedtuple的可变默认参数

时间:2015-12-08 04:23:40

标签: python namedtuple

我遇到了一个简单的方法,让命名元组使用来自here的默认参数。

from collections import namedtuple
Node = namedtuple('Node', 'val left right')
Node.__new__.__defaults__ = (None, None, None)
Node()
  

节点(val =无,左=无,右=无)

如果您希望“正确”的默认值为空列表,您会怎么做?您可能知道,使用可变默认参数(例如列表)是否定的。

有没有一种简单的方法来实现它?

3 个答案:

答案 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=[])