선택적 키워드 인수에 대한 명명 된 튜플 및 기본값


320

긴 속이 빈 "데이터"클래스를 명명 된 튜플로 변환하려고합니다. 내 수업은 현재 다음과 같습니다.

class Node(object):
    def __init__(self, val, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

변환 후 namedtuple다음과 같이 보입니다.

from collections import namedtuple
Node = namedtuple('Node', 'val left right')

그러나 여기에 문제가 있습니다. 내 원래 클래스를 사용하면 값만 전달할 수 있었고 명명 된 / 키워드 인수에 기본값을 사용하여 기본값을 처리했습니다. 다음과 같은 것 :

class BinaryTree(object):
    def __init__(self, val):
        self.root = Node(val)

그러나 이것은 내가 모든 필드를 전달할 것으로 예상하기 때문에 리팩토링 된 명명 된 튜플의 경우에는 작동하지 않습니다. 물론 Node(val)to 의 발생을 바꿀 수 Node(val, None, None)있지만 내 취향에 맞지 않습니다.

그렇다면 많은 코드 복잡성 (메타 프로그래밍)을 추가하지 않고도 재 작성을 성공적으로 수행 할 수있는 좋은 트릭이 있습니까? 아니면 약을 삼키고 "검색 및 교체"를 계속해야합니까? :)


3
이 변환을 원하는 이유는 무엇입니까? 나는 당신의 원래 Node수업을 그대로 좋아합니다 . 명명 된 튜플로 변환하는 이유는 무엇입니까?
steveha 2012-07-05

34
현재 Node클래스와 다른 클래스는 여러 필드가있는 간단한 데이터 홀더 값 개체 이기 때문에이 변환을 수행하고 싶었습니다 ( Node그 중 하나 일뿐입니다). 이 클래스 선언은 라인 노이즈 IMHO에 지나지 않으므로 잘라 내고 싶었습니다. 왜 필요하지 않은 것을 유지합니까? :)
sasuke

클래스에 메서드 함수가 전혀 없습니까? 예를 들어, .debug_print()트리를 걷고 인쇄 하는 방법이 없습니까?
steveha 2012-07-05

2
물론 BinaryTree입니다. 하지만 그것은 수업을 위한 것 입니다. Node및 기타 데이터 소유자는 특별한 방법이 ESP라는 튜플은 괜찮은 가지고 주어진 필요로하지 않는 __str____repr__표현을. :)
sasuke

좋아요, 합리적인 것 같습니다. Ignacio Vazquez-Abrams가 답을 주었다고 생각합니다. 노드의 기본값을 수행하는 함수를 사용하십시오.
steveha 2012

답변:


561

파이썬 3.7

기본값 매개 변수를 사용하십시오 .

>>> from collections import namedtuple
>>> fields = ('val', 'left', 'right')
>>> Node = namedtuple('Node', fields, defaults=(None,) * len(fields))
>>> Node()
Node(val=None, left=None, right=None)

또는 더 좋은 방법은 namedtuple보다 훨씬 좋은 새로운 데이터 클래스 라이브러리를 사용하는 것입니다.

>>> from dataclasses import dataclass
>>> from typing import Any
>>> @dataclass
... class Node:
...     val: Any = None
...     left: 'Node' = None
...     right: 'Node' = None
>>> Node()
Node(val=None, left=None, right=None)

Python 3.7 이전

설정 Node.__new__.__defaults__기본값으로.

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

Python 2.6 이전

설정 Node.__new__.func_defaults기본값으로.

>>> from collections import namedtuple
>>> Node = namedtuple('Node', 'val left right')
>>> Node.__new__.func_defaults = (None,) * len(Node._fields)
>>> Node()
Node(val=None, left=None, right=None)

주문

모든 버전의 Python에서 namedtuple에있는 것보다 적은 수의 기본값을 설정하면 가장 오른쪽 매개 변수에 기본값이 적용됩니다. 이를 통해 일부 인수를 필수 인수로 유지할 수 있습니다.

>>> Node.__new__.__defaults__ = (1,2)
>>> Node()
Traceback (most recent call last):
  ...
TypeError: __new__() missing 1 required positional argument: 'val'
>>> Node(3)
Node(val=3, left=1, right=2)

Python 2.6 ~ 3.6 용 래퍼

여기에 당신을위한 래퍼가 있습니다. 이것은 당신이 (선택적으로) 기본값을 None. 이것은 필수 인수를 지원하지 않습니다.

import collections
def namedtuple_with_defaults(typename, field_names, default_values=()):
    T = collections.namedtuple(typename, field_names)
    T.__new__.__defaults__ = (None,) * len(T._fields)
    if isinstance(default_values, collections.Mapping):
        prototype = T(**default_values)
    else:
        prototype = T(*default_values)
    T.__new__.__defaults__ = tuple(prototype)
    return T

예:

>>> Node = namedtuple_with_defaults('Node', 'val left right')
>>> Node()
Node(val=None, left=None, right=None)
>>> Node = namedtuple_with_defaults('Node', 'val left right', [1, 2, 3])
>>> Node()
Node(val=1, left=2, right=3)
>>> Node = namedtuple_with_defaults('Node', 'val left right', {'right':7})
>>> Node()
Node(val=None, left=None, right=7)
>>> Node(4)
Node(val=4, left=None, right=7)

23
보자 ... 당신의 한 줄짜리 대답 : a) 가장 짧고 / 간단한 대답, b) 공간 효율성을 보존하고, c) 깨지지 않음 isinstance... 모든 찬성, 단점 없음 ... 너무 나쁘다. 그 파티. 이것이 최고의 답변입니다.
Gerrat 2014 년

1
래퍼 버전의 한 가지 문제점 : 내장 collections.namedtuple과 달리이 버전은 def ()가 다른 모듈에 포함 된 경우 피클 가능 / 다중 프로세스 직렬화 가능하지 않습니다.
Michael Scott Cuthbert

2
나는이 대답이 내 자신보다 낫기 때문에 찬성 투표를했습니다. 그러나 내 자신의 대답이 계속 upvoted되는 것은 유감입니다.
Justin Fay 2015 년

4
@ishaaq, 문제는 (None)튜플이 아니라는 것 None입니다. (None,)대신 사용 하면 제대로 작동합니다.
Mark Lodato

4
우수한! 다음을 사용하여 기본값 설정을 일반화 할 수 있습니다.Node.__new__.__defaults__= (None,) * len(Node._fields)
ankostis

146

namedtuple을 서브 클래 싱하고 __new__메서드를 재정의했습니다 .

from collections import namedtuple

class Node(namedtuple('Node', ['value', 'left', 'right'])):
    __slots__ = ()
    def __new__(cls, value, left=None, right=None):
        return super(Node, cls).__new__(cls, value, left, right)

이것은 클래스로 위장한 팩토리 함수의 생성이 수행하지 않는 직관적 인 유형 계층을 보존합니다.


7
명명 된 튜플의 공간 효율성을 유지하기 위해 슬롯 및 필드 속성이 필요할 수 있습니다.
Pepijn 2014-04-07

어떤 이유로 사용되는 __new__경우 호출되지 않습니다 _replace.

1
IMHO가 이것보다 더 나은 솔루션 인 @ marc-lodato 답변을 살펴보십시오.
Justin Fay

1
그러나 @ marc-lodato의 대답은 하위 클래스가 다른 기본값을 갖는 기능을 제공하지 않습니다
Jason S

1
@JasonS, 나는 하위 클래스가 다른 기본값을 갖는 것이 LSP를 위반할 수 있다고 의심합니다 . 그러나 하위 클래스는 더 많은 기본값을 원할 수 있습니다 . 어쨌든 서브 클래스 는 justinfay의 method 를 사용 하고 기본 클래스는 Marc의 method를 사용하는 것이 좋습니다.
Alexey

96

함수로 감싸십시오.

NodeT = namedtuple('Node', 'val left right')

def Node(val, left=None, right=None):
  return NodeT(val, left, right)

15
이것은 영리하고 좋은 옵션이 될 수 있지만, 중단으로 인해 문제를 일으킬 수도 있습니다 isinstance(Node('val'), Node). 이제 True를 반환하는 대신 예외를 발생시킵니다. 좀 더 장황하지만 @justinfay의 대답 (아래) 은 유형 계층 정보를 적절하게 보존하므로 다른 사람들이 Node 인스턴스와 상호 작용할 경우 더 나은 방법 일 것입니다.
가브리엘 그랜트

4
이 답변의 간결함이 마음에 듭니다. 아마도 위 주석의 우려는 함수 def make_node(...):가 클래스 정의 인 것처럼 가장하는 대신 이름을 지정하여 해결할 수 있습니다 . 이러한 방식으로 사용자는 함수에서 유형 다형성을 확인하려는 유혹을받지 않고 튜플 정의 자체를 사용합니다.
user1556435

사람들이 isinstance잘못 사용하도록 오해하지 않는 변형에 대한 내 대답을 참조하십시오 .
Elliot Cameron

74

함께 typing.NamedTuple파이썬에서 3.6.1+ 당신은 기본 값과 NamedTuple 필드 유형 약어를 모두 제공 할 수 있습니다. typing.Any전자 만 필요한 경우 사용 :

from typing import Any, NamedTuple


class Node(NamedTuple):
    val: Any
    left: 'Node' = None
    right: 'Node' = None

용법:

>>> Node(1)
Node(val=1, left=None, right=None)
>>> n = Node(1)
>>> Node(2, left=n)
Node(val=2, left=Node(val=1, left=None, right=None), right=None)

또한 기본값과 선택적 변경이 모두 필요한 경우 Python 3.7은 일부 (많은?) 경우에 명명 된 튜플을 대체 할 수 있는 데이터 클래스 (PEP 557) 를 가질 것입니다.


참고 : Python에서 주석 ( :매개 변수 및 변수의 경우 뒤에 표현식 ->, 함수의 경우 뒤에 표현식) 의 현재 사양의 한 가지 단점은 정의 시간 *에 평가된다는 것 입니다. 따라서 "클래스의 전체 본문이 실행되면 클래스 이름이 정의되기 때문에" 'Node'위의 클래스 필드에 대한 주석은 NameError를 피하기 위해 문자열이어야합니다.

이런 종류의 유형 힌트를 "순방향 참조"( [1] , [2] )라고하며 PEP 563을 사용하면 Python 3.7+는 __future__순방향 참조를 사용할 수 있는 가져 오기 (기본적으로 4.0에서 활성화 됨)를 갖게됩니다. 따옴표없이 평가를 연기합니다.

* AFAICT 전용 로컬 변수 주석은 런타임에 평가되지 않습니다. (출처 : PEP 526 )


4
이것은 3.6.1+ 사용자를위한 가장 깨끗한 솔루션 인 것 같습니다. 이 예는 입력 필드에 대한 힌트 혼란 (약간) 유의 left하고 right(즉, Node) 정의되는 클래스와 동일한 형태이기 때문에, 문자열로 기록되어야한다.
101

1
@ 101, 감사합니다. 이에 대한 메모를 답변에 추가했습니다.
monk-time

2
관용구의 아날로그는 무엇입니까 my_list: List[T] = None self.my_list = my_list if my_list is not None else []? 이와 같은 기본 매개 변수를 사용할 수 없습니까?
weberc2

@ weberc2 좋은 질문입니다! 변경 가능한 def에 대한이 해결 방법인지 확실하지 않습니다. 값은 typing.NamedTuple. 그러나 데이터 클래스 를 사용 Field 하면 default_factory속성 과 함께 객체를 사용할 수 있습니다 . 이를 위해 관용구를 my_list: List[T] = field(default_factory=list).
monk-time

21

다음은 문서에서 바로 나온 예입니다 .

_replace ()를 사용하여 프로토 타입 인스턴스를 사용자 정의하여 기본값을 구현할 수 있습니다.

>>> Account = namedtuple('Account', 'owner balance transaction_count')
>>> default_account = Account('<owner name>', 0.0, 0)
>>> johns_account = default_account._replace(owner='John')
>>> janes_account = default_account._replace(owner='Jane')

따라서 OP의 예는 다음과 같습니다.

from collections import namedtuple
Node = namedtuple('Node', 'val left right')
default_node = Node(None, None, None)
example = default_node._replace(val="whut")

그러나 여기에 제공된 다른 답변 중 일부가 더 좋습니다. 완전성을 위해 이것을 추가하고 싶었습니다.


2
+1. 그들이 꽤 유용 해 보이는 _것과 같은 방법 (기본적으로 사적인 것을 의미 함)을 사용 하기로 결정한 것은 매우 이상 replace합니다.
sasuke

@sasuke-저도 궁금합니다. 대신 공백으로 구분 된 문자열로 요소를 정의하는 것은 이미 약간 이상합니다 *args. 많은 것들이 표준화되기 전에 언어에 추가되었을 수 있습니다.
Tim Tisdall 2015-08-24

12
_프리픽스는 사용자 정의 튜플 필드의 이름과 충돌 방지한다 (관련 문서 시세 "유효한 파이썬 식별자는 밑줄로 시작하는 이름 이외의 필드 명을 위해 사용될 수있다."). 공백으로 구분 된 문자열의 경우 몇 번의 키 입력을 저장하는 것 뿐이라고 생각합니다 (원하는 경우 문자열 시퀀스를 전달할 수 있음).
Søren Løvborg 2015 년

1
아, 예, 명명 된 튜플의 요소에 속성으로 액세스하는 것을 잊었으므로이 _경우 많은 의미가 있습니다.
Tim Tisdall 2015 년

2
귀하의 솔루션은 간단하고 최고입니다. 나머지는 다소 추한 IMHO입니다. 나는 작은 변화를 하나만 할 것입니다. default_node 대신 IntelliSense에서 더 나은 경험을 제공하기 때문에 node_default를 선호합니다. node 입력을 시작하면 필요한 모든 것을 받았습니다. :)
Pavel Hanpari

19

내장 namedtuple만으로 쉬운 방법이 있는지 잘 모르겠습니다. 이 기능을 가진 recordtype 이라는 멋진 모듈 이 있습니다.

>>> from recordtype import recordtype
>>> Node = recordtype('Node', [('val', None), ('left', None), ('right', None)])
>>> Node(3)
Node(val=3, left=None, right=None)
>>> Node(3, 'L')
Node(val=3, left=L, right=None)

2
아, 타사 패키지를 사용할 수는 없지만 recordtype향후 작업에는 확실히 흥미로워 보입니다. +1
sasuke

모듈은 매우 작고 단일 파일 이므로 항상 프로젝트에 추가 할 수 있습니다.
jterrace

충분히 공평하지만, 순수한 명명 된 튜플 솔루션을 위해 더 많은 시간을 기다릴 것이지만 이것이 허용됨으로 표시하기 전에 거기에 하나가 있다는 것입니다! :)
sasuke

동의 순수한 파이썬은 좋을 것입니다, 그러나 나는 하나가 있다고 생각하지 않습니다 :(
jterrace

3
그것은 recordtype변경 가능하지만 namedtuple그렇지 않다는 점에 유의하십시오 . 객체를 해시 할 수 있도록하려면 중요 할 수 있습니다 (클래스로 시작했기 때문에 그렇지 않은 것 같습니다).
bavaza

14

다음은 justinfay의 답변에서 영감을 얻은 더 간결한 버전입니다.

from collections import namedtuple
from functools import partial

Node = namedtuple('Node', ('val left right'))
Node.__new__ = partial(Node.__new__, left=None, right=None)

7
그 조심 Node(1, 2)이 레시피 작업을하지 않지만, @ justinfay의 대답에서 작동합니다. 그렇지 않으면 꽤 멋집니다 (+1).
jorgeca 2014

13

python3.7 +에는 새로운 defaults = 키워드 인자가 있습니다.

기본값기본값None 이거나 반복 가능한 기본값 일 수 있습니다 . 기본값이있는 필드는 기본값 이 없는 필드 뒤에 와야 하므로 가장 오른쪽 매개 변수에 기본값 이 적용됩니다. fieldName에이 예를 들어, ['x', 'y', 'z']및 디폴트는 (1, 2), 다음 x, 필요한 인수 될 것입니다 y기본값으로 사용됩니다 1z기본값으로 설정됩니다 2.

사용 예 :

$ ./python
Python 3.7.0b1+ (heads/3.7:4d65430, Feb  1 2018, 09:28:35) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections import namedtuple
>>> nt = namedtuple('nt', ('a', 'b', 'c'), defaults=(1, 2))
>>> nt(0)
nt(a=0, b=1, c=2)
>>> nt(0, 3)  
nt(a=0, b=3, c=2)
>>> nt(0, c=3)
nt(a=0, b=1, c=3)

7

짧고 간단하며 사람들이 isinstance부적절하게 사용하도록 유도하지 않습니다 .

class Node(namedtuple('Node', ('val', 'left', 'right'))):
    @classmethod
    def make(cls, val, left=None, right=None):
        return cls(val, left, right)

# Example
x = Node.make(3)
x._replace(right=Node.make(4))

5

누락 된 모든 인수 를 초기화하는 약간 확장 된 예제 None:

from collections import namedtuple

class Node(namedtuple('Node', ['value', 'left', 'right'])):
    __slots__ = ()
    def __new__(cls, *args, **kwargs):
        # initialize missing kwargs with None
        all_kwargs = {key: kwargs.get(key) for key in cls._fields}
        return super(Node, cls).__new__(cls, *args, **all_kwargs)

5

Python 3.7 : defaultsnamedtuple 정의 에 매개 변수 도입 .

문서에 표시된 예 :

>>> Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
>>> Account._fields_defaults
{'balance': 0}
>>> Account('premium')
Account(type='premium', balance=0)

여기에서 자세한 내용을 읽어보십시오 .


4

다음을 사용할 수도 있습니다.

import inspect

def namedtuple_with_defaults(type, default_value=None, **kwargs):
    args_list = inspect.getargspec(type.__new__).args[1:]
    params = dict([(x, default_value) for x in args_list])
    params.update(kwargs)

    return type(**params)

이것은 기본적으로 기본값으로 명명 된 튜플을 생성하고 필요한 매개 변수 만 재정의 할 수있는 가능성을 제공합니다. 예를 들면 다음과 같습니다.

import collections

Point = collections.namedtuple("Point", ["x", "y"])
namedtuple_with_defaults(Point)
>>> Point(x=None, y=None)

namedtuple_with_defaults(Point, x=1)
>>> Point(x=1, y=None)

4

@Denis와 @Mark의 접근 방식 결합 :

from collections import namedtuple
import inspect

class Node(namedtuple('Node', 'left right val')):
    __slots__ = ()
    def __new__(cls, *args, **kwargs):
        args_list = inspect.getargspec(super(Node, cls).__new__).args[len(args)+1:]
        params = {key: kwargs.get(key) for key in args_list + kwargs.keys()}
        return super(Node, cls).__new__(cls, *args, **params) 

그것은 위치 인수와 혼합 케이스로 튜플을 만드는 것을 지원해야합니다. 테스트 사례 :

>>> print Node()
Node(left=None, right=None, val=None)

>>> print Node(1,2,3)
Node(left=1, right=2, val=3)

>>> print Node(1, right=2)
Node(left=1, right=2, val=None)

>>> print Node(1, right=2, val=100)
Node(left=1, right=2, val=100)

>>> print Node(left=1, right=2, val=100)
Node(left=1, right=2, val=100)

>>> print Node(left=1, right=2)
Node(left=1, right=2, val=None)

또한 TypeError를 지원합니다.

>>> Node(1, left=2)
TypeError: __new__() got multiple values for keyword argument 'left'

3

이 버전은 읽기가 더 쉽습니다.

from collections import namedtuple

def my_tuple(**kwargs):
    defaults = {
        'a': 2.0,
        'b': True,
        'c': "hello",
    }
    default_tuple = namedtuple('MY_TUPLE', ' '.join(defaults.keys()))(*defaults.values())
    return default_tuple._replace(**kwargs)

이것은 객체를 두 번 생성해야하는만큼 효율적이지 않지만 모듈 내부에 기본 듀플을 정의하고 함수가 줄 바꾸기를 수행하도록하여 변경할 수 있습니다.


3

namedtuple데이터 클래스로 사용 하고 있기 때문에 파이썬 3.7은 @dataclass바로 이러한 목적을 위해 데코레이터를 도입 할 것이며 물론 기본값을 가지고 있음을 알아야 합니다.

문서의 예 :

@dataclass
class C:
    a: int       # 'a' has no default value
    b: int = 0   # assign a default value for 'b'

해킹보다 훨씬 깨끗하고 읽기 쉽고 사용 가능 namedtuple합니다. namedtuple3.7이 도입되면서 s의 사용량 이 감소 할 것이라고 예측하는 것은 어렵지 않습니다 .


2

영감을받은 이 대답 다른 질문에 대한, 여기에 따라 내 제안 된 솔루션 메타 클래스 및 사용 super(제대로 subcalssing 핸들 미래). justinfay의 답변 과 매우 유사합니다 .

from collections import namedtuple

NodeTuple = namedtuple("NodeTuple", ("val", "left", "right"))

class NodeMeta(type):
    def __call__(cls, val, left=None, right=None):
        return super(NodeMeta, cls).__call__(val, left, right)

class Node(NodeTuple, metaclass=NodeMeta):
    __slots__ = ()

그때:

>>> Node(1, Node(2, Node(4)),(Node(3, None, Node(5))))
Node(val=1, left=Node(val=2, left=Node(val=4, left=None, right=None), right=None), right=Node(val=3, left=None, right=Node(val=5, left=None, right=None)))

2

recordtype을 사용하는 jterrace의 대답은 훌륭하지만 라이브러리 작성자는 자신의 namedlist 프로젝트 를 사용하도록 권장합니다.이 프로젝트는 변경 가능한 ( namedlist) 및 변경 불가능한 ( namedtuple) 구현을 모두 제공합니다 .

from namedlist import namedtuple
>>> Node = namedtuple('Node', ['val', ('left', None), ('right', None)])
>>> Node(3)
Node(val=3, left=None, right=None)
>>> Node(3, 'L')
Node(val=3, left=L, right=None)

1

다음은 기본 인수가있는 명명 된 튜플에 대한 멋진 구문이 포함 된 짧고 간단한 일반 답변입니다.

import collections

def dnamedtuple(typename, field_names, **defaults):
    fields = sorted(field_names.split(), key=lambda x: x in defaults)
    T = collections.namedtuple(typename, ' '.join(fields))
    T.__new__.__defaults__ = tuple(defaults[field] for field in fields[-len(defaults):])
    return T

용법:

Test = dnamedtuple('Test', 'one two three', two=2)
Test(1, 3)  # Test(one=1, three=3, two=2)

축소 :

def dnamedtuple(tp, fs, **df):
    fs = sorted(fs.split(), key=df.__contains__)
    T = collections.namedtuple(tp, ' '.join(fs))
    T.__new__.__defaults__ = tuple(df[i] for i in fs[-len(df):])
    return T

0

NamedTupleAdvanced Enum (aenum)라이브러리 의 클래스 와 class구문을 사용하면 매우 간단합니다.

from aenum import NamedTuple

class Node(NamedTuple):
    val = 0
    left = 1, 'previous Node', None
    right = 2, 'next Node', None

한 가지 잠재적 인 단점은 __doc__기본값이있는 모든 속성 에 대한 문자열 요구 사항입니다 (단순 속성의 경우 선택 사항). 사용 중에는 다음과 같이 보입니다.

>>> Node()
Traceback (most recent call last):
  ...
TypeError: values not provided for field(s): val

>>> Node(3)
Node(val=3, left=None, right=None)

이것이 갖는 장점 justinfay's answer:

from collections import namedtuple

class Node(namedtuple('Node', ['value', 'left', 'right'])):
    __slots__ = ()
    def __new__(cls, value, left=None, right=None):
        return super(Node, cls).__new__(cls, value, left, right)

단순함뿐만 아니라되고 metaclass기반이 아닌 exec계.


0

또 다른 해결책 :

import collections


def defaultargs(func, defaults):
    def wrapper(*args, **kwargs):
        for key, value in (x for x in defaults[len(args):] if len(x) == 2):
            kwargs.setdefault(key, value)
        return func(*args, **kwargs)
    return wrapper


def namedtuple(name, fields):
    NamedTuple = collections.namedtuple(name, [x[0] for x in fields])
    NamedTuple.__new__ = defaultargs(NamedTuple.__new__, [(NamedTuple,)] + fields)
    return NamedTuple

용법:

>>> Node = namedtuple('Node', [
...     ('val',),
...     ('left', None),
...     ('right', None),
... ])
__main__.Node

>>> Node(1)
Node(val=1, left=None, right=None)

>>> Node(1, 2, right=3)
Node(val=1, left=2, right=3)

-1

덜 유연하지만 더 간결한 Mark Lodato의 래퍼 버전이 있습니다. 필드와 기본값을 사전으로 사용합니다.

import collections
def namedtuple_with_defaults(typename, fields_dict):
    T = collections.namedtuple(typename, ' '.join(fields_dict.keys()))
    T.__new__.__defaults__ = tuple(fields_dict.values())
    return T

예:

In[1]: fields = {'val': 1, 'left': 2, 'right':3}

In[2]: Node = namedtuple_with_defaults('Node', fields)

In[3]: Node()
Out[3]: Node(val=1, left=2, right=3)

In[4]: Node(4,5,6)
Out[4]: Node(val=4, left=5, right=6)

In[5]: Node(val=10)
Out[5]: Node(val=10, left=2, right=3)

4
dict주문을 보장하지 않습니다.
Ethan Furman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.