Постановка проблемы
Есть разные варианты этой проблемы, что все спрашивают то же самое:
- Как динамически создавать функцию в Python?
- Как определить функцию во время выполнения?
- Как определить функцию программно?
- Как создать функцию из строки?
Есть много способов ответить на эти вопросы – большинство веб-ресурсов предоставляют решения, которые настолько ненужны, я даже не знаю, что они думают! Мы начнем с простого решения и работать на нашем пути вверх по сложности. 😉.
Например, вы можете определить десять функций F_0
, F_1
, …, F_9 программно, что делает что-то такое как Печать его идентификатор функции. Вы можете сделать следующее:
def f_0(): print(0) def f_1(): print(1) def f_2(): print(2) def f_3(): print(3) def f_4(): print(4) def f_5(): print(5) def f_6(): print(6) def f_7(): print(7) def f_8(): print(8) def f_9(): print(9) f_0() f_1() f_2() f_3() f_4() f_5() f_6() f_7() f_8() f_9()
Желаемый выход был бы:
0 1 2 3 4 5 6 7 8 9
Тем не менее, это вряд ли можно считать элегантным кодом из-за ручного труда, участвующего в копировании и вставках, и ненужное пространство, необходимое для этого.
Начнем с подхода Brute-Force для решения любой такой проблемы:
Метод 1: EXEC ()
EXEC ()
Функция может принимать любой исходный код в виде строки и запустить его в вашем скрипте. Это идеальный способ динамически создавать функцию в Python!
💡 Встроенный Python встроенный EXEC () выполняет код Python, который вы проходите в виде строки или исполняемого объекта. Это называется динамическим выполнением, потому что, в отличие от нормального статического кода Python, вы можете генерировать код и выполнить его во время выполнения. Таким образом, вы можете запустить программно созданный код Python.
Вот как вы можете использовать EXEC ()
Функция для определения 10 функций программно и запустить их впоследствии:
# Define functions f_0 to f_9 for i in range(10): exec(f"def f_{i}(): print({i})") # Run functions f_0 to f_9 for i in range(10): exec(f"f_{i}()")
Вывод:
0 1 2 3 4 5 6 7 8 9
Вы можете использовать dir ()
Функция, чтобы проверить, действительно ли функции определены в пространство имен :
>>> dir() ['__annotations__', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'f_0', 'f_1', 'f_2', 'f_3', 'f_4', 'f_5', 'f_6', 'f_7', 'f_8', 'f_9', 'i']
Они есть!
Однако использование функции EXEC () также не особенно элегантна. И он открывает все виды опасных способов борьбы с вашим кодом. (Если вы задумаетесь, что, проверьте наш учебник на блог Finxter).
Похожие учебники: Python Exec () – руководство хакера к опасной функции
Метод 2: Функция завод
Более элегантный способ решить нашу проблему будет создать функциональную фабрику – функцию, которая создает другие функции программно и возвращает их в качестве объектов функций. Затем вы можете использовать Callable объекты для запуска данных динамически созданных функций.
# Define factory def factory(argument): def f(): print(argument) return f # Define functions functions = [] for i in range(10): functions.append(factory(i)) # Run functions for f in functions: f()
Код состоит из трех шагов:
- Сначала определите функцию завода, которая динамически создает локальную функцию
F
Видно только в Область текущего выполнения функции. ФункцияF
Можете сделать все пользовательские вещи, которые вы хотите сделать. - Во-вторых, определите все динамически созданные функции программно в
для
петля и Добавить их в список переменных. - В-третьих, перейти на все Список Значения и вызовите их для запуска программно созданных функций.
Естественно, вы также можете использовать анонимные лямбда-функции для сжимания определения фабрики функции:
# Define factory def factory(argument): return lambda : print(argument)
Вывод одинаково:
0 1 2 3 4 5 6 7 8 9
Вот немного фона на лямбда-исчислении:
💡 Функция лямбда это анонимная функция в Python. Он начинается с ключевого слова лямбда, а затем разделенный запятыми списком нулевых или более аргументов, а затем толстой кишкой и возвращаемой экспрессией. Например, лямбда х, у, z: x + y + z
рассчитал бы сумму трех ценностей аргумента х + y + z
Отказ
Метод 3: Функция декоратор
Для понимания я быстро вводим функциональную модель декоратора, который может быть полезен, если вы хотите динамически создавать функцию из шаблона, тогда как у вас есть абсолютный контроль над количеством аргументов, используемых динамически созданными функциями:
def factory(*args, **kwargs): def f(): print(args) print(kwargs) return f # Create functions dynamically f_1 = factory('hi', 'Pete') f_2 = factory(1, 2, 3, alice = 18, bob = 24) f_3 = factory([1, 2, 3], a=1, b=2, c=3) # Execute functions f_1() f_2() f_3()
Вывод:
('hi', 'Pete') {} (1, 2, 3) {'alice': 18, 'bob': 24} ([1, 2, 3],) {'a': 1, 'b': 2, 'c': 3}
Как вы можете видеть, вы можете «Hard-Code» любое поведение во внутреннюю функцию на основе заводских аргументов, чтобы настроить функции динамически созданы.
Этот шаблон обычно используется для Функциональные декораторы , но это также работает для нашей проблемы.
Метод 4: функциональный фабричный объект
Зрелое решение состоит в том, чтобы динамически создавать пользовательский класс и использовать внутренний метод для программно создания функционального поведения, назначая внешнее имя методу и использовать его как нормальную функцию:
class F: def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs def f(self): print(self.args) print(self.kwargs) f_1 = F('hi', 'Pete').f f_2 = F(1, 2, 3, alice = 18, bob = 24).f f_3 = F([1, 2, 3], a=1, b=2, c=3).f f_1() f_2() f_3()
Вывод такой же, как в наших предыдущих Метод 3 :
('hi', 'Pete') {} (1, 2, 3) {'alice': 18, 'bob': 24} ([1, 2, 3],) {'a': 1, 'b': 2, 'c': 3}
Для получения дополнительной информации на классах, проверьте наш чит-лист:
Связанный : Python OOP Cheat лист
Работая в качестве исследователя в распределенных системах, доктор Кристиан Майер нашел свою любовь к учению студентов компьютерных наук.
Чтобы помочь студентам достичь более высоких уровней успеха Python, он основал сайт программирования образования Finxter.com Отказ Он автор популярной книги программирования Python One-listers (Nostarch 2020), Coauthor of Кофе-брейк Python Серия самооставленных книг, энтузиаста компьютерных наук, Фрилансера и владелец одного из лучших 10 крупнейших Питон блоги по всему миру.
Его страсти пишут, чтение и кодирование. Но его величайшая страсть состоит в том, чтобы служить стремлению кодер через Finxter и помогать им повысить свои навыки. Вы можете присоединиться к его бесплатной академии электронной почты здесь.