22 August 2017

Некоторые приемы функционального программирования в Python

PythonFunctional Programming

Привет, Хабр!
В этой статье я хотел бы рассказать о том, что пришло в Python из функциональных языков программирования. Заинтересовавшихся прошу под кат.


Генераторы списков


Это легко и просто: вместо


l = []
for x in range(10):
    if x % 2 == 0:
        l.append(x)

мы пишем


l = [x for x in range(10) if x % 2 == 0]

Коротко и понятно.


Как это работает в функциональных языках

В Haskell тоже самое буде выглядеть так:


let l = [x | x <- [0..10], x `mod` 2 == 0]

Лямбды


Допустим, мы пишем графический интерфейс и у нас есть функция button(**kwargs), где допустимые именованные аргументы: text — для текста, width — для ширины, height — для высоты и command — для callback-функции:


def callback(event):
    print("Button pressed")
button(text="Press me", width=32, height=16, command=callback)

Обратите внимание, насколько маленький у нас callback, неужели его нелзя пропихнуть аргументом? Можно! Нам помогут лямбды:


button(text="Press me", width=32, height=16, command=lambda x: print("Button pressed"))

Чисто и легко!


Как это работает в функциональных языках

В Haskell передача функции в качестве аргумента встречается на каждом шагу, например функция map берет функцию и список и возвращает список, к каждому элементу которого была применена эта функция:


map (\x -> x+1) [1..10]

На Python это:


map(lambda x: x+1, [x for x in range(1, 10)])

Правда, в Python нет map.
upd: map есть!


Карринг


Карринг (каррирование) — это когда мы передаем старой функции один или несколько аргументов, чтобы получить новую, которая принимает остальные (спасибо AnutaU за более точное определение). Например: print — это функция (я использую Python 3), у нее есть именованный аргумент end — конец строки, по умолчанию он равен "\n". Я хочу не переходить на новую строку, тогда пишу


print(str, end="")

Давайте сделаем функцию printf, которая не будет переходить на новую строку


def printf(*args, **kwargs):
    kwargs["end"] = ""
    print(*args, **kwargs)

Коряво, можно и проще:


from functools import partial

printf = partial(print, end = "")

Вот он, карринг — мы говорим, что хотим точно такой же, но с перламутровыми пуговицами функцию print, но чтобы end был равен "". Все просто.


Как это работает в функциональных языках

И снова Haskell: у нас есть функция +, которая берет два аргумента, мы говорим:


let plusTwo = (+2)

теперь у меня есть функция, которая прибавляет 2 к единственному аргументу.


У меня все, если вы знаете, что еще есть в Python из функциональщины — прошу в комментарии.
Вопросы и отзывы туда же.

Tags:python3functional programmingfunctoolscurryinglist comprehensionslambdas
Hubs: Python Functional Programming
-3
5.5k 35
Comments 13
Top of the last 24 hours