Вызов функции модуля с помощью ее имени (строки)

Как лучше всего вызвать функцию, заданную строкой с именем функции в программе на Python. Например, допустим, у меня есть модуль foo, и у меня есть строка, содержимое которой "bar". Как лучше всего вызвать foo.bar()?

Мне нужно получить возвращаемое значение функции, вот почему я не использую eval. Я понял, как это сделать, используя eval для определения временной функции, которая возвращает результат вызова этой функции, но я надеюсь, что есть более элегантный способ сделать это.

Решение

Предполагает модуль foo с методом bar:

import foo
method_to_call = getattr(foo, 'bar')
result = method_to_call()

Вы можете сократить строки 2 и 3 до:

result = getattr(foo, 'bar')()

если это имеет больше смысла для вашего случая использования.

Вы можете использовать getattr подобным образом для методов, связанных с экземпляром класса, методов на уровне модуля, методов класса... список можно продолжить.

Комментарии (12)
locals()["myfunction"]()

или

globals()["myfunction"]()

locals возвращает словарь с текущей локальной таблицей символов. globals возвращает словарь с глобальной таблицей символов.

Комментарии (4)

Решение Патрика, вероятно, самое чистое. Если вам нужно динамически подхватывать модуль, вы можете импортировать его следующим образом:

module = __import__('foo')
func = getattr(module, 'bar')
func()
Комментарии (6)

Просто простой вклад. Если класс, который мы должны привести в качестве примера, находится в том же файле, мы можем использовать что-то вроде этого:

# Get class from globals and create an instance
m = globals()['our_class']()

# Get the function (from the instance) that we need to call
func = getattr(m, 'function_name')

# Call it
func()

Например:

class A:
    def __init__(self):
        pass

    def sampleFunc(self, arg):
        print('you called sampleFunc({})'.format(arg))

m = globals()['A']()
func = getattr(m, 'sampleFunc')
func('sample arg')

# Sample, all on one line
getattr(globals()['A'](), 'sampleFunc')('sample arg')

И, если не класс:

def sampleFunc(arg):
    print('you called sampleFunc({})'.format(arg))

globals()['sampleFunc']('sample arg')
Комментарии (0)

Учитывая последовательность, с полным путем питона к функции, это - то, как я пошел о получении результата упомянутой функции:

import importlib
function_string = 'mypackage.mymodule.myfunc'
mod_name, func_name = function_string.rsplit('.',1)
mod = importlib.import_module(mod_name)
func = getattr(mod, func_name)
result = func()
Комментарии (1)

Лучший ответ согласно [Питон, программируя часто задаваемые вопросы] (https://docs.python.org/3/faq/programming.html#how-do-i-use-strings-to-call-functions-methods) был бы:

functions = {'myfoo': foo.bar}

mystring = 'myfoo'
if mystring in functions:
    functions[mystring]()

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

Комментарии (0)

Ответ (я надеюсь), никто никогда не хотел

Оценка как поведение

getattr(locals().get("foo") or globals().get("foo"), "bar")()

Почему бы не добавить автоимпортирование

getattr(
    locals().get("foo") or 
    globals().get("foo") or
    __import__("foo"), 
"bar")()

В случае, если у нас есть дополнительные словари, мы хотим проверить

getattr(next((x for x in (f("foo") for f in 
                          [locals().get, globals().get, 
                           self.__dict__.get, __import__]) 
              if x)),
"bar")()

Мы должны пойти глубже

getattr(next((x for x in (f("foo") for f in 
              ([locals().get, globals().get, self.__dict__.get] +
               [d.get for d in (list(dd.values()) for dd in 
                                [locals(),globals(),self.__dict__]
                                if isinstance(dd,dict))
                if isinstance(d,dict)] + 
               [__import__])) 
        if x)),
"bar")()
Комментарии (0)

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

myFnName  = "MyFn"
myAppName = "MyApp"
app = sys.modules[myAppName]
fn  = getattr(app,myFnName)
Комментарии (1)

Попробуйте это. В то время как это все еще использует оценку, она только использует его для , вызывают функцию от тока context. Затем у Вас есть реальная функция, чтобы использовать, как Вы желаете.

Главная льгота для меня от этого - то, что Вы получите любые связанные с оценкой ошибки при вызове функции. Тогда Вы доберетесь только связанные с функцией ошибки, когда Вы будете звонить.

def say_hello(name):
    print 'Hello {}!'.format(name)

# get the function by name
method_name = 'say_hello'
method = eval(method_name)

# call it like a regular function later
args = ['friend']
kwargs = {}
method(*args, **kwargs)
Комментарии (4)

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

.__getattribute__()(<params>)

Я использую питона 2.66

Надежда это помогает

Комментарии (4)

Как этот вопрос Как динамично назвать методы в классе, используя назначение названия метода на переменную [дубликат] отмеченный как дубликат как этот, я публикую связанный ответ здесь:

Сценарий, метод в классе хотят назвать другой метод на том же классе динамично, я добавил некоторые детали к оригинальному примеру, который предлагает некоторый более широкий сценарий и ясность:

class MyClass:
    def __init__(self, i):
        self.i = i

    def get(self):
        func = getattr(MyClass, 'function{}'.format(self.i))
        func(self, 12)   # This one will work
        # self.func(12)    # But this does NOT work.

    def function1(self, p1):
        print('function1: {}'.format(p1))
        # do other stuff

    def function2(self, p1):
        print('function2: {}'.format(p1))
        # do other stuff

if __name__ == "__main__":
    class1 = MyClass(1)
    class1.get()
    class2 = MyClass(2)
    class2.get()

Продукция (Пайтон 3.7.x)

function1: 12

function2: 12

Комментарии (0)

Это - простой ответ, это позволит Вам очищать экран, например. Есть два примера ниже с оценкой и должностным лицом, которое напечатает 0 наверху после очистки (если you' ре используя Windows, изменитесь 'ясный' 'cls', Linux и пользователи Mac уезжают, как, например), или просто выполните его, соответственно.

eval("os.system(\"clear\")")
exec("os.system(\"clear\")")
Комментарии (0)