Модуль functools
Модуль functools
містить деякі функції вищого порядку. Функція вищого порядку приймає одну або більше функцій як вхідні дані та повертає нову функцію. Найкориснішим інструментом у цьому модулі є функція functools.partial
.
Для програм, написаних у функціональному стилі, іноді потрібно конструювати варіанти існуючих функцій, в яких деякі з параметрів заповнені. Розгляньмо Python-функцію f(a, b, c)
; можливо, ви захочете створити нову функцію g(b, c)
, яка буде еквівалентна f(1, b, c)
; ви заповнюєте значення одного з параметрів f()
. Це називається "часткове застосування функції".
Конструктор для partial()
приймає аргументи (function, arg1, arg2, ..., kwarg1=value1, kwarg2=value2)
. Отриманий об'єкт є викликаним, тому ви можете просто викликати його, щоб викликати function
з заповненими аргументами.
Ось невеликий, але реалістичний приклад:
import functools
def log(message, subsystem):
"""Записати вміст 'message' у вказану підсистему."""
print('%s: %s' % (subsystem, message))
server_log = functools.partial(log, subsystem='server')
server_log('Не вдалося відкрити сокет')
functools.reduce(func, iter, [initial_value])
кумулятивно виконує операцію на всіх елементах ітерованого об'єкту, і тому не може бути застосованою до нескінченних ітерованих об'єктів. func повинна бути функцією, яка приймає два елементи та повертає одне значення. functools.reduce
бере перші два елементи A і B, повернуті ітератором, та обчислює func(A, B)
. Потім запитує третій елемент, C, обчислює func(func(A, B), C)
, об'єднує цей результат з четвертим елементом та продовжує, поки ітерований об'єкт не буде вичерпано. Якщо початкове значення вказане, воно використовується як початкова точка, і func(initial_value, A)
є першим обчисленням:
import operator, functools
print(functools.reduce(operator.concat, ['A', 'BB', 'C'])) # 'ABBC'
print(functools.reduce(operator.mul, [1, 2, 3], 1)) # 6
print(functools.reduce(operator.mul, [], 1)) # 1
Якщо ітерований об'єкт не повертає жодного значення, виникає виняток TypeError
:
import operator, functools
functools.reduce(operator.concat, []) # TypeError: reduce() of empty sequence with no initial value
Якщо ви використовуєте operator.add
з functools.reduce
, ви додасте всі елементи ітерованого об'єкта. Цей випадок настільки поширений, що існує спеціальний вбудований метод sum
для його обчислення:
import functools, operator
print(functools.reduce(operator.add, [1, 2, 3, 4], 0)) # 10
print(sum([1, 2, 3, 4])) # 10
print(sum([])) # 0
Для багатьох випадків використання functools.reduce
, однак, може бути зрозуміліше просто написати очевидний цикл for
:
import functools, operator
# Замість:
product = functools.reduce(operator.mul, [1, 2, 3], 1)
# Ви можете написати:
product = 1
for i in [1, 2, 3]:
product *= i
print(product)
Пов'язана функція — це itertools.accumulate(iterable, func=operator.add)
. Вона виконує те саме обчислення, але замість повернення лише кінцевого результату, accumulate()
повертає ітератор, який також видає кожен частковий результат:
itertools.accumulate([1, 2, 3, 4, 5]) =>
1, 3, 6, 10, 15
itertools.accumulate([1, 2, 3, 4, 5], operator.mul) =>
1, 2, 6, 24, 120
Модуль operator
Модуль operator
згадувався раніше. Він містить набір функцій, що відповідають операторам Python. Ці функції часто корисні у функціональному стилі коду, оскільки вони позбавляють вас від написання тривіальних функцій, які виконують одну операцію.
Деякі з функцій у цьому модулі:
- Математичні операції:
add()
,sub()
,mul()
,floordiv()
,abs()
, ... - Логічні операції:
not_()
,truth()
. - Побітові операції:
and_()
,or_()
,invert()
. - Порівняння:
eq()
,ne()
,lt()
,le()
,gt()
, іge()
. - Ідентичність об'єктів:
is_()
,is_not()
.
Зверніться до документації модуля operator для повного списку.
Текст на цій сторінці є перекладом "Functional Programming HOWTO", автор: A. M. Kuchling. Інформація про копірайт: History and License.