Вызов неизвестных функций Python - PullRequest
6 голосов
/ 13 апреля 2009

Это было лучшее имя, которое я мог придумать для темы, и ни один из моих поисков не дал информации, относящейся к вопросу.

Как вызвать функцию из строки, т.е.

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
    call f

Ответы [ 7 ]

19 голосов
/ 13 апреля 2009

Вы можете использовать встроенные в Python locals () для получения локальных объявлений, например:

def f():
    print "Hello, world"

def g():
    print "Goodbye, world"

for fname in ["f", "g"]:
    fn = locals()[fname]
    print "Calling %s" % (fname)
    fn()

Вы можете использовать модуль "imp" для загрузки функций из пользовательских файлов Python, что дает вам немного больше гибкости.

Использование locals () гарантирует, что вы не сможете вызвать универсальный python, в то время как с помощью eval вы можете в конечном итоге установить для вашей строки что-то не так

f = 'open("/etc/passwd").readlines'
print eval(f+"()")

или аналогичный, и в конечном итоге ваши программы делают то, что вы не ожидаете, что это будет возможно. Использование подобных трюков с locals () и dicts в целом просто даст злоумышленникам KeyErrors.

15 голосов
/ 13 апреля 2009

как вы не знаете название вызываемой функции? Сохраните функции вместо имени:

functions_to_call = [int, str, float]

value = 33.5

for function in functions_to_call:
    print "calling", function
    print "result:", function(value)
8 голосов
/ 13 апреля 2009

Что-то в этом роде ... когда я смотрел на указатели функций в Python ..

def myfunc(x):
    print x

dict = {
    "myfunc": myfunc
}

dict["myfunc"]("hello")

func = dict.get("myfunc")
if callable(func):
    func(10)
6 голосов
/ 13 апреля 2009

Посмотрите на функцию getattr:

http://docs.python.org/library/functions.html?highlight=getattr#getattr

import sys

functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
  getattr(sys.modules[__name__], f)()
2 голосов
/ 13 апреля 2009
functions_to_call = ["func_1", "func_2", "func_3"]

for f in functions_to_call:
    eval(f+'()')

Отредактировано, чтобы добавить:

Да, eval () вообще плохая идея, но это то, что ищет OP.

1 голос
/ 14 апреля 2009

Не используйте eval! Это почти никогда не требуется, функции в python являются просто атрибутами, как и все остальное, и доступны либо с помощью getattr в классе, либо с помощью locals():

>>> print locals()
{'__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': None,
 '__name__': '__main__',
 'func_1': <function func_1 at 0x74bf0>,
 'func_2': <function func_2 at 0x74c30>,
 'func_3': <function func_3 at 0x74b70>,
}

Поскольку это словарь, вы можете получить функции с помощью клавиш DICT func_1, func_2 и func_3:

>>> f1 = locals()['func_1']
>>> f1
<function func_1 at 0x74bf0>
>>> f1()
one

Итак, решение без обращения к eval:

>>> def func_1():
...     print "one"
... 
>>> def func_2():
...     print "two"
... 
>>> def func_3():
...     print "three"
... 
>>> functions_to_call = ["func_1", "func_2", "func_3"]
>>> for fname in functions_to_call:
...     cur_func = locals()[fname]
...     cur_func()
... 
one
two
three
1 голос
/ 13 апреля 2009

См. eval и скомпилируйте функции.

Эта функция также может быть использована для выполнения объектов произвольного кода (например, созданных compile ()). В этом случае передайте объект кода вместо строки. Если объект кода был скомпилирован с exec в качестве аргумента kind, возвращаемое значение eval () будет None.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...