将 namedtuple 中的信息作为参数传递的更好方法

better way to pass information from namedtuple as args

我想从与函数签名共享相同名称的 namedtuple 中给函数值,如果该名称不存在于签名中,则跳过它。

import collections
row = collections.namedtuple('row', ['b', 'a', 'c', 'd'])
row1 = row(1,2,3,4)
def assign_rows(a, b, c):
    print(a, b, c)
assign_rows(*row1)

Returns错误

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-c5dc816f0d5d> in <module>
----> 1 assign_rows(*row1)

TypeError: assign_rows() takes 3 positional arguments but 4 were given

有两个问题,最明显的是上面的错误,而且我希望参数尊重 namedtuple 的名称,所以 a=row1.a, b=row1.b, c=row1.c。有没有一个巧妙的方法来做到这一点?

您可以将命名元组作为关键字参数传递给函数,方法是将其转换为字典并使用双星运算符:

assign_rows(**row1._asdict())

这仍然会给您带来问题,即您在元组中有一个函数不期望的额外参数 (d),这将导致错误。

如果您不介意更改函数,请将 **kwargs 添加到函数签名的末尾。这将抑制错误:

def assign_rows(a, b, c, **kwargs):
    print(a, b, c)

如果您打算在代码的其他地方使用该函数,那不是一个干净的解决方案,因为它会抑制在某些情况下可能有用的错误消息。在这种情况下,您可以将 namedtuple 与函数签名匹配,例如。

import inspect 

def namedtuple_to_func_args(ntuple, fn_def):
    params = inspect.signature(fn_def).parameters
    tuple_dict = ntuple._asdict()
    return {p : tuple_dict[p] for p in params.keys()}

然后使用

import collections
row = collections.namedtuple('row', ['b', 'a', 'c', 'd'])
row1 = row(1,2,3,4)
def assign_rows(a, b, c):
    print(a, b, c)
args = namedtuple_to_func_args(row1, assign_rows)
assign_rows(**args)

根据周围的逻辑,它还有其他的变体,作为装饰器可能会更整洁。您还应该考虑 juanpa 在关于仅使用 a=row1.a 等的评论中所说的话,因为它简单且高效,具体取决于您使用此模式的频率以及它需要的灵活性