#python #design-patterns #globals
#python #шаблоны проектирования #глобальный
Вопрос:
Допустим, я пишу библиотечный модуль a.py вот так
def call_func(f):
""" invoke func by its func str """
return eval(f)()
и определяемая пользователем функция находится в модуле b.py,
from a import call_func
def b():
return "b"
call_func("b")
Это будет ошибкой, поскольку в модуле a функция b не отображается.
Поскольку функция b находится в пространстве пользователя, с точки зрения библиотеки a, определяемая пользователем функция b неизвестна.
Возможно, можно использовать функцию register в a.py , но я не знаю, как это сделать. Или, может быть, есть альтернативные способы?
Спасибо!
Ответ №1:
Не используйте eval
практически никогда.
Вы могли бы использовать dict функций и объединить это с globals()
(или, может быть, еще лучше иметь явный dict функций, например {"b": b}
):
def call_func(funcs, f):
return funcs[f]()
def b():
print("b was called")
call_func(globals(), "b")
Комментарии:
1. это точно работает!! большое спасибо! @AKX почему вы избегаете eval?
2. Потому
eval()
что позволяет запускать любой произвольный код, а не только именованные функции. Если бы кому-то удалось передать"__import__('os').system('rm -rf ~/*)"
asf
, у вас больше не осталось бы домашнего каталога.
Ответ №2:
Просто передайте саму функцию.
a.py
def call_func(f):
return f()
b.py
from a import call_func
def b():
return "b"
call_func(b)
Комментарии:
1. Это может быть хорошей идеей для других сценариев. но в этом случае библиотека была разработана для вызова пользовательской функции b через str. На самом деле он будет вызывать пользовательские функции (может быть более одной) через шаблон. Поэтому предпочтительнее str. Спасибо за ваш вклад…