Часто использование настоящих функций вроде enliven() гораздо прозрачнее, чем использование лямбд. Лямбды наиболее полезны в случаях, когда вам нужно определить множество мелких функций и запомнить все их имена. В частности, вы можете использовать лямбды в графических пользовательских интерфейсах, чтобы определить
Генераторы
В Python
>>> sum(range(1, 101))
5050
Каждый раз, когда вы итерируете через генератор, он отслеживает, где он находился во время последнего вызова, и возвращает следующее значение. Это отличает его от обычной функции, которая не помнит о предыдущих вызовах и всегда начинает работу с первой строки и в неизменном состоянии.
Если вы хотите создать потенциально большую последовательность и ее код слишком велик для того, чтобы создать включение генератора, напишите
>>> def my_range(first=0, last=10, step=1):
…·····number = first
…·····while number < last:
…·········yield number
…·········number += step
…
Это нормальная функция:
>>> my_range
И она возвращает объект генератора:
>>> ranger = my_range(1, 5)
>>> ranger
Мы можем проитерировать по этому объекту генератора:
>>> for x in ranger:
…·····print(x)
…
1
2
3
4
Декораторы
Иногда вам нужно модифицировать существующую функцию, не меняя при этом ее исходный код. Зачастую нужно добавить выражение для отладки, чтобы посмотреть, какие аргументы были туда переданы.
• *args и **kwargs;
• внутренние функции;
• функции в качестве аргументов.
Функция document_it() определяет декоратор, который:
• выведет имя функции и значение переданных в нее аргументов;
• запустит функцию с полученными аргументами;
• выведет результат;
• вернет модифицированную функцию, готовую для использования.
Код будет выглядеть так:
>>> def document_it(func):
…·····def new_function(*args, **kwargs):
…·········print('Running function:', func.__name__)
…·········print('Positional arguments:', args)
…·········print('Keyword arguments:', kwargs)
…·········result = func(*args, **kwargs)
…·········print('Result:', result)
…·········return result
…·····return new_function
Независимо от того, какую функцию func вы передадите document_it(), вы получите новую функцию, которая содержит дополнительные выражения, добавляемые document_it(). Декоратор не обязательно должен запускать код функции func, но функция document_it() вызовет часть func, поэтому вы получите результат работы функции func, а также дополнительные данные:
>>> def add_ints(a, b):
…····return a + b
…
>>> add_ints(3, 5)
8
>>> cooler_add_ints = document_it(add_ints)··# мануальное присваивание декоратора
>>> cooler_add_ints(3, 5)
Running function: add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8
В качестве альтернативы мануальному присваиванию декоратора, показанному выше, просто добавьте конструкцию @
>>> @document_it
… def add_ints(a, b):
…·····return a + b
…
>>> add_ints(3, 5)
Start function add_ints
Positional arguments: (3, 5)