编写函数以传递参数或参数元组的大多数 pythonic 方式

Most pythonic way to write a function to either pass in arguments or a tuple of arguments

编写函数以传递参数或 tuple/list 个参数的最 pythonic 方法是什么?

例如,函数 add 可以接受 add(1, 2)add((1, 2)) 的参数,并且都输出 3.

我目前拥有的:(有效,但看起来不太好)

def add(*args):
    if len(args) == 1:
        return (args[0][0] + args[0][1])
    if len(args) == 2:
        return args[0] + args[1]
    else:
        print "error: add takes in one or two arguments"

我不喜欢的是:

  1. 我必须打印有关传递一个或两个参数的错误
  2. args[0][0] 看起来非常难读
  3. 这样,很难判断传入的参数代表什么(他们没有名字)

如果您的函数接受特定数量的参数,那么最符合 Python 风格的方法是 而不是 这样做。相反,如果用户有一个带有参数的元组,你可以让他们在调用函数时解压它们。例如

def add(a, b):
   return a + b

那么调用者可以做

add(1,2)

t = (1,2)
add(*t)

你唯一想要接受参数序列或单个参数的时候是你可以有任意(非零)数量的参数(例如 maxmin 内置函数)在这种情况下你只需要使用 *args

如果您只能接受有限数量的参数,那么专门询问这些参数会更有意义。如果您可以接受任意数量的参数,那么 *args 范式在循环遍历它时效果很好。混合搭配这两者不是很优雅。

def add(*args):
    total = 0
    for i in args:
        total += i
    return total

>>> add(1, 2, 3)
6

(我知道我们可以在那里使用 sum(),但我试图让它看起来更通用)

我不知道这是否是最 "pythonic" 的方式,但它会做你想做的事:

def add(a, b=None):
    return a+b if b is not None else sum(a)

本着 python 鸭子打字的精神,如果您看到 1 个参数,请假设它扩展为 2 个参数。如果它是 2,假设它是加在一起的两件事。如果它违反了您的规则,则引发异常,例如 python 会在函数调用中执行。

def add(*args):
    if len(args) == 1:
        args = args[0]
    if len(args) != 2:
        raise TypeError("add takes 2 arguments or a tuple of 2 arguments")
    return args[0] + args[1]

装修师最适合这份工作。

from functools import wraps

def tupled_arguments(f):
    @wraps(f)  # keeps name, docstring etc. of f
    def accepts_tuple(tup, *args):
        if not args:  # only one argument given
            return f(*tup)
        return f(tup, *args)
    return accepts_tuple

@tupled_arguments
def add(a, b):
    return a + b