我想知道如何做这样的事情(在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
,但我不太清楚如何去做这样做。
答案 0 :(得分:3)
您已经关闭了,您需要做的就是在调用内部函数时在元组前面添加*
(或在关键字参数的dict前面添加**
)。这称为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
第二种方法没有这个问题。
答案 1 :(得分:0)
这是一种方式:
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