如何从另一个函数调用具有任意参数的函数?

时间:2014-09-22 18:26:30

标签: python string python-2.7

我想知道如何做这样的事情(在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,但我不太清楚如何去做这样做。

2 个答案:

答案 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