当前位置: 首页 > 知识库问答 >
问题:

Python名称元组的可变默认参数

羊舌旭尧
2023-03-14

我遇到了一种巧妙的方法,让命名图普尔从这里使用默认参数。

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

节点(val=无,left=无,right=无)

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

有没有一个简单的方法来实现这一点?

共有3个答案

仲孙思源
2023-03-14

由于这个问题已经被提出,dataclass模块已经被提出并被Python接受。这个模块与namedtuples有很多重叠的用例,但是有更多的灵活性和功能。特别是,当您想为可变字段指定默认值时,您可以指定工厂函数。

from typing import List
from dataclasses import dataclass, field

@dataclass
class Node:
    val: str
    left: List["Node"] = field(default_factory=list)
    right: List["Node"] = field(default_factory=list)

在命名元组中,您指定各种字段的类型,因此在这种情况下,我必须填写一些空白,并假设< code>val是一个字符串,而< code>left和< code>right都是其他< code>Node对象的列表。

由于是类定义中赋值的左侧,因此当我们初始化 Node html" target="_blank">对象时,它们是可选参数。此外,我们可以提供一个默认值,但是我们提供了一个默认工厂,这是一个函数,每当我们初始化Node对象而不指定这些字段时,都会用0个参数调用它。

例如:

node_1 = Node('foo')
# Node(val='foo', left=[], right=[])

node_2 = Node('bar', left=[node_1])
# Node(val='bar', left=[Node(val='foo', left=[], right=[])], right=[])

node_3 = Node('baz')
# Node(val='baz', left=[], right=[])

node_4 = Node('quux', left=[node_2], right=[node_3])
# Node(val='quux', left=[Node(val='bar', left=[Node(val='foo', left=[], right=[])], right=[])], right=[Node(val='baz', left=[], right=[])])

就我个人而言,我发现对于任何我需要的不仅仅是最薄的数据容器的应用程序,我都使用< code>dataclasses而不是< code>namedtuples。

锺离阿苏
2023-03-14

公认答案中给出的方法非常有效。我看到的唯一缺点是,在创建对象和执行类似操作时,必须知道(对于其他用户)并记住使用工厂函数而不是命名的tuple类:

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
禄源
2023-03-14

你不能这样做,因为__defaults__中的值是实际的默认值。也就是说,如果你编写的函数确实有someargument=无,然后在函数体内部使用someargument=[]进行检查,如果Someargument是无其他Someargument或类似的,则相应的__defaults__条目仍然是无。换句话说,你可以用函数做到这一点,因为在函数中,你可以编写代码来做任何你想做的事情,但是你不能在命名元组中编写自定义代码。

但如果您想要默认值,只需创建一个具有该逻辑的函数,然后创建正确的namedtuple:

def makeNode(val=None, left=None, right=None):
    if right is None:
        val = []
    return Node(val, left, right)
 类似资料:
  • 问题内容: 我正在尝试将冗长的空心“数据”类转换为命名元组。我的班级目前看起来像这样: 转换为它后看起来像: 但是这里有一个问题。我的原始类允许我只传入一个值,并通过对named / keyword参数使用默认值来处理默认值。就像是: 但这在重构的元组中不起作用,因为它希望我传递所有字段。我当然可以替换to的出现,但这并不是我喜欢的。 那么,是否存在一个可以使我的重写成功而又不增加很多代码复杂性(

  • 我正在尝试将一个较长的空心“数据”类转换为命名元组。我的类目前看起来像这样: 转换为它看起来像这样: 但是这里有一个问题。我最初的类允许我只传入一个值,并通过为命名/关键字参数使用默认值来处理默认值。类似于: 但这在我重构的命名元组中不起作用,因为它要求我传递所有字段。我当然可以将出现的替换为,但这不符合我的喜好。 那么,是否有一个很好的技巧可以让我的重写成功而不会增加很多代码复杂性(元编程),或

  • 问题内容: 有没有一种方法可以在python ElementTree中定义默认/无前缀的命名空间?这似乎不起作用… 这也不是: 可以,但是我必须在每个元素前加上前缀: 在OSX上使用Python 3.5。 编辑:如果答案为“否”,您仍然可以获得赏金:-)。我只是想要一个花了很多时间使用它的人的明确“否”。 问题答案: 没有简单的方法可以透明地处理默认名称空间。正如您已经提到的,为空名称空间分配非空

  • 我们知道,在调用函数时如果不指定某个参数, Python 解释器会抛出异常。为了解决这个问题,Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。 Python 定义带有默认值参数的函数,其语法格式如下: def 函数名(...,形参名,形参名=默认值):     代码块

  • 问题内容: 我以为我可以在Python 2的函数调用中在变长位置参数之后使用命名参数,但是在导入python类时得到了提示。例如,我正在使用以下“ get”方法编写: 错误看起来像: 我希望能够以几种方式调用该方法: 等等 问题答案: 它确实有效,但仅在Python 3中有效。请参阅PEP 3102。浏览“新功能”文档后,似乎没有2.x向后移植,因此您很不走运。您必须接受任何关键字参数()并手动对

  • 问题内容: 长时间修改Python的任何人都被以下问题咬伤(或弄成碎片): Python新手希望此函数始终返回仅包含一个元素的列表[5]。结果是非常不同的,并且非常令人惊讶(对于新手而言): 我的一位经理曾经第一次遇到此功能,因此称其为“严重的设计缺陷”。我回答说,这种行为有一个基本的解释,如果您不了解内部原理,那确实是非常令人困惑和意外的。但是,我无法(对自己)回答以下问题:在函数定义而不是函数