Модуль 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.