Рубрики
Без рубрики

Как динамически создавать функцию в Python?

Состав проблем Есть разные варианты этой проблемы, которые все спрашивают то же самое: как динамически создавать функцию в Python? Как определить функцию во время выполнения? Как определить функцию программно? Как создать функцию из строки? Как создать функцию из строки? Есть много способов ответить на эти вопросы – – большинство веб-ресурсов предоставляют такие решения … Как динамически создавать функцию в Python? Прочитайте больше “

Автор оригинала: Chris.

Постановка проблемы

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

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