命名为元组和可选关键字参数

问题:

我试图将一个长空的“数据”类转换为一个命名的元组。我的课程目前看起来像这样:

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)的事件替换为Node(val, None, None),但不是我的喜好。
那么存在一个好的技巧,可以使我的重写成功,而不增加大量的代码复杂性(元编程),或者我应该吞下药丸,继续进行“搜索和替换”? 🙂

回答:

Node.__new__.__defaults__(或Python 1之前的Node.__new__.func_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)

您也可以通过使__defaults__列表缩短来获得必需的字段。

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

包装纸

这是一个很好的包装器,甚至可以让您(可选)将默认值设置为除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)

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: Named tuple and optional keyword arguments

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

29 − 26 =