каковы некоторые хорошие способы вызова определяемой пользователем функции из библиотеки python?

#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 ~/*)" as f , у вас больше не осталось бы домашнего каталога.

Ответ №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. Спасибо за ваш вклад…