Python Learning Notes 07_Functional Programming

Keywords: Lambda Python

Higher-order function

  • Variables can point to functions, that is, functions themselves can also be assigned to variables.
  • The function name is also a variable.
  • Functions are passed in as parameters. Such functions are called higher-order functions.

map/reduce

  • The map() function receives two parameters, one is a function and the other is Iterable. The map functions the incoming function into each element of the sequence in turn, and returns the result as a new Iterator.

    <<< def f(x):
            return x * x
    
    <<< r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9])
    <<< list(r)
    [1, 4, 9, 16, 25, 36, 49, 64, 81]
    
    # The first parameter passed in by map() is f, the function object itself.
    
    
    # Because the result r is an Iterator, Iterator is an inert sequence.
    
    
    # So the whole sequence is computed by the list() function and a list is returned.
    
  • reduce() function.

    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4) # f is two parameters
    reduce(f, [x1, x2, x3, x4]) = f(f(f(f(x1), x2), x3), x4) # f is a parameter
    
    # Functions converted from str to int
    
    from functools import reduce
    def str2int(s):
        def fn(x, y):
            return x * 10 + y
        def char2num(s):
            return {'0':0, '1':1, '2':2, '3',3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}[s]
        return reduce(fn, map(char2num, s))
    # str2float
    
    CHAR_TO_FLOAT = {
        '0': 0,
        '1': 1,
        '2': 2,
        '3': 3,
        '4': 4,
        '5': 5,
        '6': 6,
        '7': 7,
        '8': 8,
        '9': 9,
        '.': -1
    }
    def str2float(s):
        nums = map(lamba ch: CHAR_TO_FLOAT[ch], s)
        point = 0
        def to_float(f, n):
            nonlocal point
            if n == -1:
                point = 1
                return f
            if point == 0:
                return f * 10 + n
            else:
                point = point * 10
                return f + n /point
        return reduce(to_float, num, 0.0)

filter

  • filter() acts on each element in turn, and then decides whether to retain or discard the element based on whether the return value is True or False.
  • The filter() function returns an Iterator, requiring a list() function to get all the results and return a list.

    # In a list, delete even numbers and keep only odd numbers
    
    def is_odd(n):
        return n % 2 == 1
    
    list(filter(is_odd,[1, 2, 3, 4, 5, 6, 9]))
    # Delete empty strings from a sequence
    
    def not_empty(s):
        return s and s.strip()
    
    list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
    #!/usr/bin/env python3
    
    
    # -*- coding: utf-8 -*-
    
    
    # Using filter to find prime numbers
    
    
    def main():
        for n in primes():
            if n < 1000:
                print(n)
            else:
                break
    
    
    # Construct an odd sequence starting from 3. Note that this is a generator and an infinite sequence.
    
    def _odd_iter():
        n = 1
        while True:
            n = n + 2
            yield n
    
    
    # Define filter function
    
    def _not_divisible(n):
        return lambda x: x % n > 0
    
    
    # Define the generator and keep returning to the next prime
    
    def primes():
        yield 2
        it = _odd_iter() # Initial sequence
        while True:
            n = next(it) # The next number of returned sequences
            yield n
            it = filter(_not_divisible(n), it) # Constructing New Sequences
    
    if __name__ == '__main__':
        main()

sorted

  • Sort the strings, ignore case, sort them alphabetically, and pass the key function to sorted.

    sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)
  • For reverse sorting, you can pass in the third parameter reverse=True

    from operator import itemgetter
    students = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
    
    print(sorted(students, key = itemgetter(0)))
    print(sorted(students key = lambda t: t[1]))
    print(sorted(students, key = itemgetter(1), reverse = True))

Return function

  • Function as return value

    def lazy_sum(*args):
    def sum():
    ax = 0
    for n in args:
    ax = ax + n
    return ax
    return sum


    <<< f1 = lazy_sum(1, 3, 5, 7, 9)
    <<< f2 = lazy_sum(1, 3, 5, 7, 9)
    <<< f1 == f2
    False
  • Closure. The returned function is not executed immediately. The returned function does not refer to loop variables or variables that will change later.

Anonymous function

  • Anonymous functions can only have one expression, without writing return, the return value is the result of the expression. Anonymous function is also a function object, which can be assigned to a variable and then called by variables.

    <<< list(map(lambda x: x * x), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    # The keyword lambda denotes anonymous functions, and the x before the colon denotes function parameters.

Decorator

  • Decorator, add function dynamically during code running.

    import functools
    
    def log(func):
    @functools.wraps(func)
        def wrapper(*args, **kw):
            print('call %s():' % func.__name__)
            return func(*args, **kw)
        return wrapper
    
    @log
    def now():
        print('2015-3-25')
    
    <<< now()
    
    # now = log(now)
    
    call now():
    2015-3-25
    import functools
    
    def log(text):
        def decorator(func):
            @functools.wrap(func)
            def wropper(*args, **kw):
                print('%s %s' % (text, func.__name__))
                return func(*args, **kw)
            return wrapper
        return decorator
    
    @log('execute')
    def now():
        print('2015-3-25')
    
    <<< now()
    
    # now = log('execute')(now)
    
    execute now():
    2015-3-25
    
    <<< now.__name__
    'wrapper'

Partial function

  • functools.partial. When creating a partial function, you can actually accept three parameters: function object, * args and ** kw.

    def int2(x, base = 2):
        return int(x, base)
    <<< import functools
    <<< int2 = functools.partial(int, base = 2)

Posted by armyguydave69 on Sat, 23 Mar 2019 08:15:54 -0700