在函数中传递函数名作为参数
我想把一个函数的名字当作参数传递给另一个函数,但我遇到了一个错误:TypeError: 'str' object is not callable
。下面是这个问题的一个简单例子:
def doIt(a, func, y, z):
result = z
result = func(a, y, result)
return result
def dork1(arg1, arg2, arg3):
thing = (arg1 + arg2) / arg3
return thing
def dork2(arg1, arg2, arg3):
thing = arg1 + (arg2 / arg3)
return thing
当我这样调用 doIt 函数时:
var = 'dork1'
ned = doIt(3, var, 4, 9)
print (ned)
我得到了:
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
ned = doIt(3, var, 4, 9)
File "<pyshell#2>", line 3, in doIt
result = func(a, y, result)
TypeError: 'str' object is not callable
9 个回答
7
不要传递一个函数的名字。
要传递这个函数本身。
fun = dork1
ned = doIt(3, fun, 4, 9)
print (ned)
8
我很高兴找到这个,不知道之前有没有人回答过。我的解决方案如下:
def doIt(func, *args):
func_dict = {'dork1':dork1,'dork2':dork2}
result = func_dict.get(func)(*args)
return result
def dork1(var1, var2, var3):
thing = (float(var1 + var2) / var3)
return thing
def dork2(var1, var2, var3):
thing = float(var1) + (float(var2) / var3)
return thing
可以这样运行:
func = 'dork2'
ned = doIt(func,3, 4, 9)
print ned
31
如果你想传递函数的名字,就像你说的那样,当然你不能直接调用它——为什么要“调用一个名字”呢?这没有意义。
如果你想调用这个函数,就要传递函数本身,也就是说,绝对不是
var = 'dork1'
而是
var = dork1
不带引号!
补充说明:提问者在评论中提到,想知道如何根据函数名(作为字符串)获取函数对象。其实我刚在OSCON的一个讲座中展示了如何做到这一点——你可以从这里获取幻灯片,查看第47页,“懒加载回调”:
class LazyCallable(object):
def __init__(self, name):
self.n, self.f = name, None
def __call__(self, *a, **k):
if self.f is None:
modn, funcn = self.n.rsplit('.', 1)
if modn not in sys.modules:
__import__(modn)
self.f = getattr(sys.modules[modn],
funcn)
self.f(*a, **k)
所以你可以传递LazyCallable('somemodule.dork1')
,然后就可以快乐地生活下去了。当然,如果你不需要处理模块的话(这听起来真奇怪!),调整这段代码会很简单。