Abstrakcje oparte na funkcjach¶
W programowaniu funkcyjnym funkcje są obiektami pierwszej klasy (ang first class citizens) – oznacza to, że można je przypisywać do zmiennych, przekazywać jako argumenty do innych funkcji, a także zwracać jako wartości. Dzięki temu funkcje mogą pełnić rolę narzędzi do opisu operacji na danych w sposób modularny i abstrakcyjny.
Funkcje jako podstawowy element programu¶
Jedną z charakterystycznych cech stylu funkcyjnego jest stosowanie funkcji anonimowych, zwanych również funkcjami lambda. Umożliwiają one definiowanie krótkich, jednorazowych operacji:
1 double = lambda x: x * 2
2 print(double(5)) # wynik: 10
3
4 add = lambda a, b: a + b
5 print(add(3, 7)) # wynik: 10
Funkcje mogą być również przekazywane jako argumenty do innych funkcji. Przykład zastosowania funkcji map:
1 numbers = [1, 2, 3, 4]
2 squared = map(lambda x: x**2, numbers)
3 print(list(squared)) # wynik: [1, 4, 9, 16]
Takie podejście pozwala oddzielić logikę przetwarzania od danych, co zwiększa czytelność i reużywalność kodu.
Funkcje takie jak map, filter i reduce (z modułu functools) są typowymi przykładami narzędzi funkcyjnych dostępnych w Pythonie, które umożliwiają przekształcanie i filtrowanie zbiorów danych bez użycia pętli:
1 from functools import reduce
2
3 numbers = [1, 2, 3, 4]
4 total = reduce(lambda x, y: x + y, numbers)
5 print(total) # wynik: 10
Funkcje wyższego rzędu¶
Funkcje wyższego rzędu to funkcje, które przyjmują inne funkcje jako argumenty lub zwracają funkcje jako wynik. Stanowią one istotny element programowania funkcyjnego, umożliwiając budowę elastycznego i abstrakcyjnego kodu. Dzięki nim można tworzyć funkcje o bardziej ogólnym przeznaczeniu i w prosty sposób łączyć różne operacje.
Typowym przykładem funkcji wyższego rzędu jest funkcja, która wykonuje daną operację na każdej wartości z listy:
1 def apply_to_each(fn, values):
2 return [fn(x) for x in values]
3
4 result = apply_to_each(lambda x: x * 10, [1, 2, 3])
5 print(result) # wynik: [10, 20, 30]
Funkcje wyższego rzędu są także wykorzystywane do zwracania nowych funkcji – często wyspecjalizowanych wersji bardziej ogólnych operacji. Poniższy przykład tworzy funkcję zwracającą funkcję mnożącą przez stałą wartość:
1 def multiplier(factor):
2 def multiply(x):
3 return x * factor
4 return multiply
5
6 times3 = multiplier(3)
7 print(times3(5)) # wynik: 15
Dzięki temu możemy tworzyć nowe funkcje „w locie”, dopasowane do bieżącego kontekstu obliczeń. Takie podejście zwiększa elastyczność kodu i ułatwia jego ponowne wykorzystanie w różnych miejscach programu.