如何用另一个函数调用具有任意参数的函数?
我想知道我怎么会去这样做这样的事情(在Python 2):如何用另一个函数调用具有任意参数的函数?
def myFunction(fn, params):
return ("You called " + fn.__name__ + "(" + str(params) ")" +
" and got " + str(fn(params)))
说我有一对夫妇的功能:
def doSomething(s):
# manipulation
return s
def doAnotherThing(someInt, someOtherInt, someString):
# do something with them
return someValue
我想成为能够拨打myFunction(doSomething, "hello")
,并获得You called doSomething("hello") and got "something"
。这种方法似乎适用于采用单一输入的函数,但我无法让它适用于需要多个输入的函数,例如调用myFunction(doAnotherThing, (myInt, myOtherInt, myString))
。我想我需要做一些涉及*
和**
的事情,以便我可以任意使用关键字而不是tuple
,但我不太确定如何去做。
您已经接近了,您只需要在调用内部函数时在元组前添加一个*
(或者在关键字参数的字典前加**
)。这被称为argument unpacking。
def wrapper(fn, params, keyword_params):
return fn(*params, **keyword_params)
def myfunc(a, b, c=0):
return (a + b)/c
wrapper(myfunc, (2, 5), {'c': 3})
您还可以使用arbitrary argument lists来潜在地简化包装函数。这将允许您自动打包额外的参数以供给内部函数,而无需将它们预先打包到元组和字典中。只是使用第一种方法实际上将打破单参数的实现,为*
操作
def wrapper(fn, *params, **keyword_params): # Note the asterisks
return fn(*params, **keyword_params)
def myfunc(a, b, c=1):
return (a + b)/c
wrapper(myfunc, 2, 5, c=3) # Nicer function call
注期望一个迭代器来解压。因此,您必须始终预先打包参数或在wrapper
函数中添加一些类型检查。
def wrapper(fn, params):
return fn(*params)
def myfunc(a):
return 2*a
wrapper(myfunc, 2)
# TypeError: myfunc() argument after * must be a sequence, not int
wrapper(myfunc, (2,)) # Package the argument in a single-element tuple
# 4
第二种方法没有这个问题。
你也可以在'wrapper'的定义中包含'*'s,这样它的调用看起来就像是嵌套的:'def wrapper(fn,* params,** keyword_params)',然后你可以调用'包装(myfunc,2,5,c = 3)'。 – 2014-09-22 18:35:30
@MarkReed谢谢,添加到答案。 – 2014-09-22 18:43:54
@RogerFan可能也想明确地将打印内容添加到你的'wrapper'装饰器中。 – 2014-09-22 18:45:24
这里有一种方法:
def myFunction(fn, *params):
return ("You called " + fn.__name__ + str(params) +
" and got " + str(fn(*params)))
import math
print myFunction(math.sqrt, 4)
print myFunction(open, '/etc/passwd', 'r')
print myFunction(lambda x: x+1, 41)
结果:
You called sqrt(4,) and got 2.0
You called open('/etc/passwd', 'r') and got <open file '/etc/passwd', mode 'r' at 0x7f20e9cb65d0>
You called <lambda>(41,) and got 42
你正在寻找一个[装饰](http://simeonfranklin.com/blog/2012/jul/1/ python-decorators-in-12-steps /),我建议读一下他们做你想做的事情。 – Jack 2014-09-22 18:30:09