Python:将函数名称作为函数中的参数传递

Des*_*ond 20 python

我试图将函数的名称作为参数传递给另一个函数,但我得到一个错误:"TypeError:'str'对象不可调用".以下是该问题的简化示例:

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
Run Code Online (Sandbox Code Playgroud)

我打电话的时候是这样的:

var = 'dork1'
ned = doIt(3, var, 4, 9)
print (ned)
Run Code Online (Sandbox Code Playgroud)

我明白了:

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
Run Code Online (Sandbox Code Playgroud)

Ale*_*lli 28

如果你想传递函数的名字,就像你说的那样,当然你不能称之为 - 为什么一个人会"叫一个名字 "?这毫无意义.

如果你想调用它,传递函数本身,也就是说,最重要的是没有

var = 'dork1'
Run Code Online (Sandbox Code Playgroud)

反而

var = dork1
Run Code Online (Sandbox Code Playgroud)

没有引号!

编辑:OP在评论(!)中想知道如何在给定函数名称(作为字符串)的情况下获取函数对象.实际上我只是在我在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)
Run Code Online (Sandbox Code Playgroud)

因此,你可以LazyCallable('somemodule.dork1')永远过世,幸福生活.如果您当然不需要处理模块(这是一个必须暗示的奇怪架构! - ),则可以轻松调整此代码.

  • Desmond可能习惯于"php-style"函数名称传递,它将一个函数名称放在一个字符串中,然后传递它并调用它,它可能会被唤醒或者其他东西.*不寒而栗*. (3认同)

S.L*_*ott 5

不要传递函数名称。

通过功能。

fun = dork1
ned = doIt(3, fun, 4, 9)
print (ned)
Run Code Online (Sandbox Code Playgroud)


小智 5

我很高兴找到这个,我不知道这是否得到了回答。我对此的解决方案如下:

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
Run Code Online (Sandbox Code Playgroud)

这可以按如下方式运行:

func = 'dork2'
ned = doIt(func,3, 4, 9)
print ned
Run Code Online (Sandbox Code Playgroud)