接受扩展参数和元组的函数

B-K*_*B-K 8 python

是否有Pythonic方法来创建一个接受单独的参数和元组的函数?即实现这样的目标:

def f(*args):
    """prints 2 values 
            f(1,2)
                1 2
            f( (1,2) )
                1 2"""
    if len(args) == 1:
        if len(args[0]) != 2:
            raise Exception("wrong number of arguments")
        else:
            print args[0][0],args[0][1]
    elif len(args) == 2:
        print args[0],args[1]
    else:
            raise Exception("wrong number of arguments")
Run Code Online (Sandbox Code Playgroud)

Wil*_*sem 5

首先,我不知道这样做是否明智.假设一个人调用的函数如下:

f(*((1,4),(2,5)))
Run Code Online (Sandbox Code Playgroud)

如您所见,元组包含两个元素.但是现在由于某种原因,这个人只用一个元素来调用它(因为例如生成器没有生成两个元素):

f(*((1,4),))
Run Code Online (Sandbox Code Playgroud)

然后用户可能希望您的函数报告这个,但现在它将简单地接受它(这可能导致复杂和意外的行为).好的打印元素当然不会造成太大的伤害.但在一般情况下,后果可能更严重.

然而,一个优雅的方法是做一个简单的装饰器,首先检查是否有一个元素被喂它检查是否有一个元组元素,如果是这样,它会扩展它:

def one_tuple(f):
    def g(*args):
        if len(args) == 1 and isinstance(args[0],tuple):
            return f(*args[0])
        else:
            return f(*args)
    return g
Run Code Online (Sandbox Code Playgroud)

并将其应用于您的f:

@one_tuple
def f(*args):
    if len(args) == 2:
        print args[0],args[1]
    else:
        raise Exception("wrong number of arguments")
Run Code Online (Sandbox Code Playgroud)

因此,装饰器会one_tuple检查是否有一个元组被送入,如果是,则在将它传递给您的函数之前将其解包f.

因此,f不必考虑元组情况:它将始终被提供扩展参数并处理这些(当然也可以相反).

定义装饰器的优点是它的重用:你可以将这个装饰器应用于各种函数(从而使它更容易实现).