Слайд 1Python
Елементи функціонального програмування
Слайд 2План
Функції як об'єкти першого класу (first-class citizens)
Лямбда - вирази
Замикання
Функції вищого
порядку, каррінг функцій
Декоратори
Функції filter, map, reduce
Модулі functools, оператор, itertools
Слайд 3
Поняття функціонального програмування
Функціональне програмування - розділ дискретної математики і парадигма програмування,
в якій процес обчислення трактується як обчислення значень функцій в математичному розумінні останніх (на відміну від функцій як підпрограм в процедурному програмуванні).
Функціональне програмування передбачає обходитися обчисленням результатів функцій від вихідних даних і результатів інших функцій, і не передбачає явного зберігання стану програми. Відповідно, не передбачає воно і змінність цього стану (на відміну від імперативного, де однією з базових концепцій є змінна, що зберігає своє значення і дозволяє змінювати його в міру виконання алгоритму)
Слайд 4Характерні риси функціонального програмування
Рішення задачі записується як сукупність незалежних від зовнішнього
стану функцій
Функції як об'єкти першого класу
Імутабельність (незмінюваність) даних
Використання функцій вищого порядку
Каррінг і часткове застосування функцій
Слайд 5Функція як об'єкт першого класу
Об'єкт називають «об'єктом першого класу», якщо він:
може бути збережений в змінній або структурах даних;
може передаватися в функцію як аргумент;
може бути повернутий з функції як результат;
може бути створений під час виконання програми;
внутрішньо самоідентифікований (незалежний від іменування).
Термін «об'єкт» використовується тут в загальному сенсі, і не обмежується об'єктами мови програмування.
В Python, як і в функціональних мовах, функції є об'єктами першого класу.
Слайд 6Приклад 1
def add(x,y):
return x+y
def sub(x,y):
return x-y
def mul(x,y):
return x*y
def div(x,y):
return x/y
Слайд 7Приклад 1
operations ={
'+' : add,
'-' : sub,
'*' : mul,
'/' : div,
'^' : pow}
Слайд 8Приклад 1
first = float(input('First number: '))
operation = input('Operation: ')
second = float(input('Second
number: '))
result = operations[operation](first,second)
print('Result:',result)
Слайд 9Лямбда вирази
Звичайне оголошення функції:
def add(x, y):
return x + y
Використання лямбда - виразу (лямбда-функції, анонімної функції):
add = lambda x,
y: x + y
Слайд 10Приклад 2
operations ={
'+' : lambda x, y : x+y,
'-' : lambda x, y : x-y,
'*' : lambda x, y : x*y,
'/' : lambda x, y : x/y,
'^' : pow}
Слайд 11Замикання
Замикання (closure) У програмуванні - функція, в тілі якої присутні посилання
на змінні, оголошені поза тілом цієї функції в навколишньому коді і які не є її параметрами.
У разі замикання посилання на змінні зовнішньої функції дійсні всередині вкладеної функції до тих пір, поки працює вкладена функція, навіть якщо зовнішня функція закінчила роботу, і змінні вийшли з області видимості.
Замикання пов'язує код функції з її лексичним оточенням (місцем, в якому вона визначена в коді). Лексичні змінні замикання відрізняються від глобальних змінних тим, що вони не займають глобальний простір імен. Від змінних в об'єктах вони відрізняються тим, що прив'язані до функцій, а не об'єктів.
В Python будь-які функції (в тому числі і лямбда - вирази), оголошені всередині інших функцій, є повноцінними замиканнями.
Слайд 12Приклад 3
def add(x):
def two_add(y):
return x+y
return two_add
print(add(402)(45))
Слайд 13Функції вищого порядку
Функція вищого порядку - функція, що приймає в якості
аргументів інші функції або повертає іншу функцію в якості результату. Основна ідея полягає в тому, що функції мають той же статус, що й інші об'єкти даних.
Каррінг (currying) - перетворення функції від багатьох аргументів на функцію, що бере свої аргументи по одному. Це перетворення було введено М. Шейнфінкель і Г. Фреге і отримало свою назву на честь Х. Каррі.
Слайд 14Приклад 4
def add(x):
def two_add(y):
return x+y
return two_add
add_to_ten=add(10)
print(add_to_ten(2))
print(add_to_ten(12.5))
Слайд 15Приклад 5
elem = lambda value, next: {'value': value, 'next': next}
to_string =
lambda head: '' if head is None \
else str(head['value'])+' ' +to_string(head['next'])
values = elem(1,elem(2,elem(3,None)))
print(to_string(values))
Слайд 16Декоратори
Декоратор в Python - функція, яка приймає як параметр іншу функцію
(або клас) і повертає нову, модифіковану функцію (або клас), яка її замінює.
Крім того, поняття функцій вищого порядку часто застосовується і для створення декораторів: часто потрібно, щоб декоратор брав ще якісь параметри, крім об'єкта що модифікується. В такому випадку створюється функція, що створює і повертає декоратор, а при застосуванні декоратора замість вказівки імені функції-декоратора дана функція викликається.
Слайд 17Приклад 6
def decorator(fn):
def decorated_fn(*args, **kwargs):
print('Decorated
function says:')
fn(*args, **kwargs)
print()
return decorated_fn
def hello():
print('Hello!')
#hello = decorator(hello)
hello()
Слайд 18Приклад 7
def decorator(fn):
def decorated_fn(*args, **kwargs):
print('Decorated
function says:')
fn(*args, **kwargs)
print()
return decorated_fn
@decorator
def hello():
print('Hello!')
hello()
Слайд 19map, filter, reduce
Трьома класичними функціями вищого порядку, що з'явилися ще в
мові програмування LISP, які приймають функцію і послідовність, є map, filter і reduce.
map застосовує функцію до кожного елементу послідовності. В Python 2 повертає список, в Python 3 - об'єкт-ітератор.
filter залишає лише ті елементи послідовності, для яких задана функція істинна. В Python 2 повертає список, в Python 3 - об'єкт-ітератор.
reduce (в Python 2 вбудована, в Python 3 знаходиться в модулі functools) приймає функцію від двох аргументів, послідовність і опціональне початкове значення і обчислює згортку (fold) послідовності як результат послідовного застосування даної функції до поточного значення (так званому акумулятору) і наступному елементу послідовності.
Слайд 20Приклад 8
values = [2, 4, 8, 15, 42]
for square in map(lambda
x: x**2, values):
print(square)
square = list(map(lambda x: x**2, values))
print(square)
Слайд 21Приклад 9
numbers = [3, 2, -1, 0, 15, -8, -7, 3,
-3, 8]
positive_numbers = filter(lambda x: x > 0, numbers)
print(list(positive_numbers))
Слайд 22Приклад 10
from functools import reduce
numbers = [3, 2, 1, 8, -3,
-2]
product = reduce(lambda x, y: x * y, numbers)
print(product)
Слайд 23Модуль functools
Модуль functools містить велику кількість стандартних функцій вищого порядку. Деякі
з них :
lru_cache - декоратор, який кешує значення функцій, які не змінюють свій результат при незмінних аргументах; корисний для кешування даних, мемоізаціі (збереження результатів для повернення без обчислення функції) значень рекурсивних функцій (наприклад, такого типу, як функція обчислення n - го числа Фібоначчі) і т. д .;
partial - часткове застосування функції (виклик функції з меншою кількістю аргументів, ніж вона очікує, і отримання функції, яка приймає параметри що залишилися).
Слайд 24Приклад 11
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(index):
if index < 2:
return 1
else:
return fibonacci(index - 1) + fibonacci(index - 2)
for i in range(1, 1000):
print(fibonacci(i))
Слайд 25from functools import partial
def add(x,y):
return x+y
add_to_ten=partial(add,10)
print(add_to_ten(2))
print(add_to_ten(12.5))
Приклад 12
Слайд 26Модуль itertools
Модуль itertools містить функції для роботи з итераторами і створення
ітераторів. Деякі з них :
product - декартовій добуток ітераторів (для уникнення вкладених циклів for);
permutations - генерація перестановок;
combinations - генерація сполучень;
combinations_with_replacement - генерація розміщень;
chain - поєднання декількох ітераторів в один;
takewhile - отримання значень послідовності, поки значення функції - предиката для її елементів істинно;
dropwhile - отримання значень послідовності починаючи з елемента, для якого значення функції - предиката перестане бути істинно.
Слайд 27Приклад 13
from itertools import product
for i in range(1,5):
for j
in range(1,5):
#for i, j in product(range(1,5),range(1,5)):
print('{}x{}={}'.format(i,j,i*j))
Слайд 28Приклад 14
from itertools import chain
for i in chain(range(2), range(3)):
print(i)
Слайд 29Приклад 15
from itertools import permutations,
combinations,
combinations_with_replacement
print(list(permutations('ABC', 2)))
print()
print(list(combinations('ABC', 2)))
print()
print(list(combinations_with_replacement('ABC', 2)))
Слайд 30Приклад 16
from itertools import takewhile, dropwhile
numbers = [1, 4, 6, 4,
1]
predicate = lambda x: x < 5
for value in takewhile(predicate, numbers):
print(value)
print()
for value in dropwhile(predicate, numbers):
print(value)
Слайд 31Модуль operator
Модуль operator містить функції, які відповідають стандартним операторам.
Слайд 34Приклад 17
from operator import neg, mul, le
from functools import reduce, partial
print(list(map(neg,
[2, 4, 8, 9, 1])))
print(reduce(mul, [3, 4, 5]))
print(list(filter(partial(le, 5), [5, 4, 8, 1, 3, 10])))