Постановка проблемы
Есть разные варианты этой проблемы, что все спрашивают то же самое:
- Как динамически создавать функцию в 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 и помогать им повысить свои навыки. Вы можете присоединиться к его бесплатной академии электронной почты здесь.