Fundamentals of Functional Programming in Python

This post serves as a refresher and introduces some basic functional programming in Python, as well as an addition to my  previous post  on the data pipeline. The post material is divided into four parts:





  • Functional programming principles





  • The operator lambda



    , function map



    , filter



    , reduce



    and others





  • Inclusion in the sequence





  • Closure





Functional programming principles

KEY PROVISIONS:





Functional programming is a software writing technique that focuses on functions. Functions can be assigned to variables, they can be passed to other functions and spawned new functions. Python has a rich and powerful arsenal of tools that make it easy to develop function-oriented programs.





In recent years, almost all known procedural and object-oriented programming languages ​​have begun to support functional programming (FP) tools. And Python is no exception.





When talking about FP, they primarily mean the following:





  • Functions are first-class objects, that is, anything you can do with "data" can also be done with functions (like passing a function to another function as an argument).





  • . , .





  • . .





  • «» . , .





  • , (.. ). , ( ).





  • , , .





  • Β« Β» (, , ).





, . . , , . . , , - . .





, , , . , , . Python , .





.





lambda, map, filter, reduce

, Python. .





lambda

, def



, Python lambda



, -. -:





lambda _:







_ – , , – , . , :





def standard_function(x, y):
    return x + y
      
      







lambda x, y: x + y
      
      



, - , , :





>>> (lambda x, y: x+y)(5, 7)
12
      
      



, , , , , , . . ( .)





>>> lambda_function = lambda x, y: x + y
>>> lambda_function(5,7)
12
>>> func = lambda_function
>>> func(3,4)
7
>>> dic = {'1': lambda_function}
>>> dic['1'](7,8)
15
      
      



1 - , -. 2 . 4 , . 7 , , , , .





. Python map.





map

, , . . map.





Python map



– , . . map



:





map(, )







– -, – , .. , , .





>>> seq = (1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> seq2 = (5, 6, 7, 8, 9, 0, 3, 2, 1)
>>> result = map(lambda_function, seq, seq2)
>>> result
<map object at 0x000002897F7C5B38>
>>> list(result)
[6, 8, 10, 12, 14, 6, 10, 10, 10]
      
      



1 2 , seq seq2, . 3 result map, - . , map - map, 5. - map , , . – , , . , . , , . , . , , «». 6 map .





filter

. filter



, , , , . Python filter



. , . filter



:





filter(_, )







_ – -, , – , .. , , .





, is_even



:





is_even = lambda x: x % 2 == 0
      
      



, filter



:





>>> seq = (1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> filtered = filter(is_even, seq)
>>> list(filtered)
[2, 4, 6, 8]
      
      



-, :





>>> filtered = iter(filter(lambda x: x % 2 == 0, seq))
>>> list(filtered)
[2, 4, 6, 8]
      
      



, filter



-, , . , . , next



.





>>> next(filtered)
2
>>> next(filtered)
4
...
      
      



. StopIteration. ,





seq = sequence
try:
    total = next(seq)
except StopIteration:
    return
      
      



reduce

, , , reduce. reduce



functools , , , :





def reduce(fn, seq, initializer=None):
    it = iter(seq)
    value = next(it) if initializer is None else initializer
    for element in it:
        value = fn(value, element)
    return value
      
      



reduce



:





reduce(, , )







– ; -, – , .. , , , – , . – , .. , , .





. , reduce . , :





>>> seq = (1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> get_sum = lambda a, b: a + b
>>> summed_numbers = reduce(get_sum, seq)
>>> summed_numbers
45
      
      



. sentences – , , , :





>>> sentences = [".", 
>>> ...          "    , ", 
>>> ...          " ,    ."]
>>> wsum = lambda a, sentence: a + len(sentence.split())
>>> number_of_words = reduce(wsum, sentences, 0)
>>> number_of_words
13
      
      



-, wsum



, split



, len .





?





  • .





  • – -, – .





  • , , . .





  • . for



    , . . , , , , . Β« . . Β».





  • , , . , any



    , all



    .





.





zip

zip



, .. , . zip



:





zip(, , ...)







– , .. , , . zip



-, , . :





>>> x = ''
>>> y = ''
>>> zipped = zip(x, y)
>>> list(zipped)
[('', ''), ('', ''), ('', '')]
      
      



*



( , ..) . :





>>> x2, y2 = zip(*zip(x, y))
>>> x2
('', '', '')
>>> y2
('', '', '')
>>> x == ''.join(x2) and y == ''.join(y2)
True
      
      



enumerate

enumerate . enumerate:





enumerate()







– , .. , , . enumerate -, , .





, . , .





>>> lazy = enumerate(['','',''])
>>> list(lazy)
[(0, ''), (1, ''), (2, '')]
      
      



2 list



, . enumerate :





>>> convert = lambda tup: tup[1].upper() + str(tup[0])
>>> lazy = map(convert, enumerate(['','','']))
>>> list(lazy)
['0', '1', '2']
      
      



convert



1 . tup



– , tup[0]



– , tup[1]



– .





, . , Python :





squared_numbers = [x*x for x in numbers]
      
      



Python Β« Β» ( . comprehension, ), . . :





[ for in if 2]







– , , – , – , 2 – . , :





>>> numbers = [1, 2, 3, 4, 5]
>>> squared_numbers = [x*x for x in numbers]
>>> squared_numbers
[1, 4, 9, 16, 25]
      
      



:





>>> squared_numbers = []
>>> for x in numbers:
>>>     squared_numbers.append(x*x)
>>> squared_numbers
[1, 4, 9, 16, 25]
      
      



, .. , . , , .





. , . , , Python, Β« Β» , , . , , .





1.













[x*x for x in numbers]











{x:x*x for x in numbers}











{x*x for x in numbers}







set(x*x for x in numbers)











(x*x for x in numbers)







. . – , ( for



), , , .





, ( ) : , – – .





, map



filter



. , 3 map



:





>>> seq = (1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> seq2 = (5, 6, 7, 8, 9, 0, 3, 2, 1)
>>> result = [x + y for x, y in zip(seq, seq2)]
>>> result
[6, 8, 10, 12, 14, 6, 10, 10, 10]
      
      



– , . , zip



, . ( , ..)





filter



:





>>> result = [x for x in seq if is_even(x)]
>>> result
[2, 4, 6, 8]
      
      



, . – , .





, . , . . , , «» .





, . . ( , curring) – , . , , adder



:





def adder(n, m):
    return n + m
      
      



, :





def adder(n):
    def fn(m):
        return n + m
    return fn
      
      



-:





adder = lambda n: lambda m: n + m
      
      



, -, . adder



. adder(3)



, , . adder



3 3 . :





>>> sum_three = adder(3)
>>> sum_three
<function __main__.<lambda>.<locals>.<lambda>>
>>> sum_three(1)
4
      
      



adder(3)



sum_three, . sum_three



, , 3 1.





. . :





def power_generator(base):
    return lambda x: pow(x, base)
      
      



power_generator



, :





>>> square = power_generator(2#    
>>> square(2)
4
>>> cube = power_generator(3)    #    
>>> cube(2)
8
      
      



, square



cube



base



. power_generator



, , power_generator



. : – , .





. , , , . :





COUNT = 0

def count_add(x):
    global COUNT
    COUNT += x
    return COUNT
      
      



, , . , :





def make_adder():
    n = 0    

    def fn(x):
        nonlocal n
        n += x
        return n

    return fn
      
      



. , nonlocal



, , n fn. , :





>>> my_adder = make_adder()
>>> print(my_adder(5))     #  5
>>> print(my_adder(2))     #  7 (5 + 2)
>>> print(my_adder(3))     #  10 (5 + 2 + 3)

5
7
10
      
      



; . , , . . . , , . .





. Starting Out with Python.








All Articles