是否有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)
首先,我不知道这样做是否明智.假设一个人调用的函数如下:
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不必考虑元组情况:它将始终被提供扩展参数并处理这些(当然也可以相反).
定义装饰器的优点是它的重用:你可以将这个装饰器应用于各种函数(从而使它更容易实现).