Python学习笔记07_函数式编程

孤人 提交于 2020-03-08 16:40:15

高阶函数Higher-order function

  • 变量可以指向函数,即:函数本身也可以赋值给变量。
  • 函数名也是变量。
  • 把函数作为参数传入,这样的函数称为高阶函数。

map/reduce

  • map()函数,接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的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]
    # map()传入的第一个参数是f,即函数对象本身。
    # 由于结果r是一个Iterator,Iterator是惰性序列,
    # 因此通过list()函数把整个序列计算出来并返回一个list.
    
  • reduce()函数。

    reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4) # f是两个参数
    reduce(f, [x1, x2, x3, x4]) = f(f(f(f(x1), x2), x3), x4) # f是一个参数
    
    
    # str转换为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()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

  • filter()函数返回的是一个Iterator,需要用list()函数获得所有结果并返回list。

    # 在一个list中,删掉偶数,只保留奇数
    def is_odd(n):
        return n % 2 == 1
    
    list(filter(is_odd,[1, 2, 3, 4, 5, 6, 9]))
    
    # 把一个序列中的空字符串删掉
    def not_empty(s):
        return s and s.strip()
    
    list(filter(not_empty, ['A', '', 'B', None, 'C', '  ']))
    
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    # 用filter求素数
    
    def main():
        for n in primes():
            if n < 1000:
                print(n)
            else:
                break
    
    # 构造从3开始的奇数序列,注意这是一个生成器,并且是无限序列。
    def _odd_iter():
        n = 1
        while True:
            n = n + 2
            yield n
    
    # 定义筛选函数
    def _not_divisible(n):
        return lambda x: x % n > 0
    
    # 定义生成器,不断返回下一个素数
    def primes():
        yield 2
        it = _odd_iter() # 初始序列
        while True:
            n = next(it) # 返回序列的下一个数
            yield n
            it = filter(_not_divisible(n), it) # 构造新序列
    
    if __name__ == '__main__':
        main()
    

sorted

  • 对字符串排序,忽略大小写,按照字母序排序,给sorted传入key函数。
    sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)
    
  • 进行反向排序,可以传入第三个参数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))
    

返回函数

  • 函数作为返回值
    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
    
  • 闭包,返回的函数并没有立即执行,返回函数不要引用循环变量,或者后续会发生变化的变量。

匿名函数

  • 匿名函数只能有一个表达式,不用写return,返回值就是该表达式的结果。匿名函数也是一个函数对象,可以把匿名函数赋值给一个变量,再利用变量来调用该函数。
    <<< list(map(lambda x: x * x), [1, 2, 3, 4, 5, 6, 7, 8, 9])
    # 关键字lambda表示匿名函数,冒号前面的x表示函数参数。
    

装饰器

  • 装饰器,在代码运行期间动态增加功能。

    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,创建偏函数时,实际上可以接收函数对象、*args**kw这三个参数.

    def int2(x, base = 2):
        return int(x, base)
    
    <<< import functools
    <<< int2 = functools.partial(int, base = 2)
    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!