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

Когда я вызываю 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

Ответ 1

Если вы хотите передать функцию имя, как вы сказали, и вы это делаете, конечно, вы не можете ее назвать - зачем "называть имя"? Это бессмысленно.

Если вы хотите вызвать его, пропустите функцию, то есть наиболее решительно не

var = 'dork1'

а скорее

var = dork1

без кавычек!

Изменить: ОП задается вопросом (!) как получить объект функции с именем функции (в виде строки). Как бы то ни было, я просто показал, как это сделать в учебнике, которое я преподавал в OSCON (из которого я только что вернулся) - получить слайды из здесь и см. стр. 47, "Lazy-load callbacks":

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') и жить долго и счастливо. Если вам не нужно иметь дело с модулем, конечно (какая странная архитектура должна подразумевать!), Легко настроить этот код.

Ответ 2

Не передавать имя функции.

Передайте функцию.

fun = dork1
ned = doIt(3, fun, 4, 9)
print (ned)

Ответ 3

var = 'dork1'
ned = doIt(3, var, 4, 9)
print (ned)

В этом примере var - это строка. Функция doIt "вызывает" свой второй аргумент (для которого вы проходите var). Передайте вместо этого функцию.

Ответ 4

Вероятно, вы не должны этого делать, но вы можете получить функцию, используя eval()

например, для использования len,

eval("len")(["list that len is called on"])

Ответ 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

Это можно запустить следующим образом:

func = 'dork2'
ned = doIt(func,3, 4, 9)
print ned

Ответ 6

Функции являются первоклассными объектами в python. Сделайте это:

var = dork1

Если вы должны передать строку, например, ввод пользователя, то:

globals()[var]

будет искать объект функции.

Ответ 7

def run_function(function_name):
    function_name()

В этом примере вызов run_function(any_function) вызовет any_function().