Использование списка строк для выполнения функций с аргументами - PullRequest
1 голос
/ 24 мая 2019

Я хотел бы использовать объект списка для вызова функций по имени, передавая аргументы каждой функции, пока список используется в цикле. На функции нужно ссылаться как на строки, как в реальных сценариях, которые поступают из командной строки.

Функции

У меня есть следующие функции:

 def sum_a(x):
     x + 1000


 def sum_b(x):
     x + 100


 def sum_c(x):
     x + 1

Вызов

Я хотел бы выполнить функции sum_a и sum_c для x = 9.

Подход

functions_to_call = ['sum_a', 'sum_c']
x = 9
for each_call in functions_to_call:
    getattr(globals(), each_call)()

Задача

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-14-9f12b9113b60> in <module>()
      1 for each_call in functions_to_call:
----> 2     getattr(globals(), each_call)()
      3

AttributeError: 'dict' object has no attribute 'sum_a'

Ответы [ 2 ]

2 голосов
/ 24 мая 2019

Вы можете ссылаться на функции по их названию.Они ведут себя как переменные.

functions_to_call = [sum_a, sum_c]
x = 9
for each_call in functions_to_call:
    each_call(x)

Если вы хотите обратиться к функциям по имени:

functions_to_call = ['sum_a', 'sum_c']
x = 9
for each_call in functions_to_call:
    globals()[each_call](x)
1 голос
/ 24 мая 2019

Лучше обратиться к функциям напрямую:

functions_to_call = [sum_a, sum_c]
x = 9
for f in functions_to_call:
    f(x)

Для вашей конкретной задачи getattr ищет эти атрибуты в словаре, но вы хотите получить доступ к словарю, для которого выможно использовать operator.itemgetter:

>>> from operator import itemgetter
>>> x = 10
>>> itemgetter("x")(globals())
10

Окончательная версия будет выглядеть так:

from operator import itemgetter
functions_to_call = ['sum_a', 'sum_c']
x = 9
for each_call in map(itemgetter, functions_to_call):
    each_call(globals())(x)

В любом случае, вы не должны использовать globals таким образом, этолучше иметь адресный словарь:

funcs = {
    "sum_a" : sum_a,
    "sum_c" : sum_c
}
    functions_to_call = ['sum_a', 'sum_c']
    x = 9
    for each_call in functions_to_call:
        funcs.get(each_call, lambda *_: print("Selected function do not exist"))(x)
...