FUNCTIONAL PROGRAMMING CONCEPTS IN PYTHON

#WHO

Matt Gathu

Software Engineer at Jumo World

Pythonista and Rust Enthusiast

#WHAT IS FP

#FEATURES

  • Modularity

  • No shared state (purity)

  • No mutability (No side effects)

#ADVANTAGES

  • Modular Design 

  • Ease of debugging and Testing

  • Composability

  • Formal provability

  • Memoization

  • Concurrency

#FP in Python

#Language Features

First Class Functions
High Order Functions
Comprehensions
Lazy Evaluation

#First Class Functions

assigned to variables

returned as  values  ​

passed as arguments  

def handle_value_error(func):

    def wrapper(*args, **kwargs):
        
        try:
            return func(*args, **kwargs)
        except ValueError:
            return None
        
    return wrapper

#High Order Functions

map filter reduce


def upper(x):
    return x.upper()


def apply(func, args):
    return func(*args)


def map(func, sequence):
    return [apply(func, x) for x in sequence]


map(upper, ['a', 'b', 'c']) == ['A', 'B', 'C']


#Decorator Functions

 

High Order functions that apply transformation to other functions.

def auto_retry(tries=3, exc=Exception, delay=5):

    def decorator(func):

        def wrapper(*args, **kwargs):
            for trial in range(1, tries+1):
                try:
                    return func(*args, **kwargs)
                except exc:
                    time.sleep(trial * delay)
                    continue
            raise exc

        return wrapper

    return decorator


@auto_retry(exc=HTTPException)
def moyale_network_call():
    ...

#Comprehensions

based on set-builder notation.


# List Comprehensions
squares = [x**2 for x in range(10)]


# Generator Comprehensions
squares = (x**2 for x in range(10))


# Set Comprehensions
a = {x for x in 'abracadabra' if x not in 'abc'}


# Dictionary Comprehensions
squares = {x: x**2 for x in (2, 4, 6)}

#Lazy Evaluation

This is a call-by-need evaluation strategy that delays evaluation of an expression until its value is needed.


def gen_even_ints(n):
    for i in range(n):
        if i % 2 == 0:
            yield i


>>> gen = gen_even_ints(4)
>>> gen
<generator object gen_even_ints at 0x108dee258>

>>> next(gen)
0

>>> next(gen)
2

>>> next(gen)
-------------------------------------------------------
StopIteration        Traceback (most recent call last)
<ipython-input-6-8a6233884a6c> in <module>()
----> 1 next(gen)

StopIteration:

#Batteries Included

#Itertools Module

count

cycle

repeat

accumulate

chain

dropwhile

combinations

permutations

count() count(10) --> 10 11 12 13 14 ...
cycle() cycle('ABCD') --> A B C D A B C D .
repeat() repeat(10, 3) --> 10 10 10
accumulate() accumulate([1,2,3,4,5]) --> 1 3 6 10 15
chain() chain('ABC', 'DEF') --> A B C D E F

#Functools Module

partial

reduce

wraps

import functools

def log (message, subsystem):
    "Write the contents of 'message' to the specified subsystem."
    print '%s: %s' % (subsystem, message)
    ...

server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
Made with Slides.com