Документация Python неофициальный перевод
Содержание страницы

9.8. functools – Функции высшего порядка и операции с вызываемыми объектамиfunctools – Higher-order functions and operations on callable objects

Новое в версии 2.5.

Исходный код: Lib/functools.py


Модуль functools предназначен для функций высшего порядка: функций, которые действуют на или возвращают другие функции. В общем случае любой вызываемый объект может рассматриваться как функция для целей этого модуля.

Модуль functools определяет следующие функции:

functools.cmp_to_key(func)

Преобразует функцию сравнения старого стиля в ключевую функцию. Используется с инструментами, которые принимают ключевые функции (такими как sorted(), min(), max(), heapq.nlargest(), heapq.nsmallest(), itertools.groupby()). Эта функция в основном используется как переходный инструмент для программ, переносимых на Python 3, где функции сравнения больше не поддерживаются.

Функция сравнения – это любой вызываемый объект, который принимает два аргумента, сравнивает их и возвращает отрицательное число, если первый меньше второго, ноль при равенстве или положительное число, если первый больше второго. Функция ключа – это вызываемый объект, который принимает один аргумент и возвращает другое значение, используемое в качестве ключа сортировки.

Пример:

sorted(iterable, key=cmp_to_key(locale.strcoll))  # порядок сортировки с учётом локали

Примеры сортировки и краткое руководство см. в Sorting HOW TO.

Новое в версии 2.7.

functools.total_ordering(cls)

Для класса, определяющего один или несколько методов расширенного сравнения, этот декоратор класса предоставляет остальные. Это упрощает задачу определения всех возможных операций расширенного сравнения:

Класс должен определять один из __lt__(), __le__(), __gt__() или __ge__(). Кроме того, класс должен предоставлять метод __eq__().

Например:

@total_ordering
class Student:
    def __eq__(self, other):
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))
    def __lt__(self, other):
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))

Новое в версии 2.7.

functools.reduce(function, iterable[, initializer])

Это та же функция, что и reduce(). Она доступна в этом модуле, чтобы позволить писать код, более совместимый с будущими версиями Python 3.

Новое в версии 2.6.

functools.partial(func[,*args][, **keywords])

Возвращает новый объект partial, который при вызове ведёт себя как func, вызванная с позиционными аргументами args и именованными аргументами keywords. Если при вызове передаётся больше аргументов, они добавляются к args. Если передаются дополнительные именованные аргументы, они расширяют и переопределяют keywords. Примерно соответствует:

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

partial() используется для частичного применения функции, которое «замораживает» некоторую часть аргументов и/или ключевых слов функции, создавая новый объект с упрощённой сигнатурой. Например, partial() можно использовать для создания вызываемого объекта, который ведёт себя как функция int(), где аргумент base по умолчанию равен двум:

>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo.__doc__ = 'Convert base 2 string to an int.'
>>> basetwo('10010')
18
functools.update_wrapper(wrapper, wrapped[, assigned][, updated])

Обновляет функцию-обёртку wrapper, чтобы она выглядела как функция wrapped. Необязательные аргументы – кортежи, определяющие, какие атрибуты исходной функции напрямую присваиваются соответствующим атрибутам функции-обёртки, а какие атрибуты функции-обёртки обновляются соответствующими атрибутами исходной функции. Значения по умолчанию для этих аргументов – константы уровня модуля WRAPPER_ASSIGNMENTS (которая присваивает функции-обёртке атрибуты __name__, __module__ и __doc__, строку документации) и WRAPPER_UPDATES (которая обновляет __dict__ функции-обёртки, т.е. словарь экземпляра).

Основное назначение этой функции – использование в decorator-функциях, которые оборачивают декорированную функцию и возвращают обёртку. Если функция-обёртка не обновляется, метаданные возвращаемой функции будут отражать определение обёртки, а не исходной функции, что обычно не очень полезно.

functools.wraps(wrapped[, assigned][, updated])

Это удобная функция для вызова update_wrapper() в качестве декоратора функции при определении функции-обёртки. Она эквивалентна partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated). Например:

>>> from functools import wraps
>>> def my_decorator(f):
...     @wraps(f)
...     def wrapper(*args, **kwds):
...         print 'Calling decorated function'
...         return f(*args, **kwds)
...     return wrapper
...
>>> @my_decorator
... def example():
...     """докстринг"""
...     print 'Called example function'
...
>>> example()
Calling decorated function
Called example function
>>> example.__name__
'example'
>>> example.__doc__
'Docstring'

Без использования этой фабрики декораторов имя примера функции было бы 'wrapper', а строка документации исходной example() была бы потеряна.

9.8.1. partial Объектыpartial Objects

Объекты partial – это вызываемые объекты, создаваемые partial(). Они имеют три атрибута только для чтения:

partial.func

Вызываемый объект или функция. Вызовы объекта partial будут перенаправлены в func с новыми аргументами и ключевыми словами.

partial.args

Крайние левые позиционные аргументы, которые будут добавлены перед позиционными аргументами, переданными при вызове объекта partial.

partial.keywords

Ключевые аргументы, которые будут предоставлены при вызове объекта partial.

Объекты partial похожи на объекты function тем, что они вызываемы, могут быть слабыми ссылками и могут иметь атрибуты. Есть несколько важных отличий. Например, атрибуты __name__ и __doc__ не создаются автоматически. Кроме того, объекты partial, определённые в классах, ведут себя как статические методы и не превращаются в связанные методы при поиске атрибута экземпляра.