11.函数式编程:匿名函数、高阶函数、装饰器

lambda表达式

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

print(add(1, 2))

f = lambda x, y: x + y

print(f(1, 2))

匿名函数的简单使用。
匿名函数最适合的场景是需要传入函数作为参数,返回值的操作不复杂的地方
python对匿名函数的支持非常有限

三元表达式

表达式版本的if...else...
其他语言的表达式x > y ? x : y
python的表达式 x if x > y else y
三元表达式经常用在lambda匿名函数中

map

list_x = [1, 2, 3, 4, 5, 6, 7, 8]

def f1(x):
    return x * x

list_y = map(f1, list_x)
print(list_y)  # 生成的是惰性的序列
print(list(list_y))

map会对可迭代对象的每一项执行函数 f1 并返回新的可迭代对象

map与lambda

list_x = [1, 2, 3, 4, 5, 6, 7, 8]

list_y = map(lambda x: x * x, list_x)
print(list_y)  # 生成的是惰性的序列
print(list(list_y))

传入多个参数的map,将计算几个参数中长度最短的序列次数的映射(下例中为6次)

# map

list_x = [1, 2, 3, 4, 5, 6, 7, 8]
list_y = [1, 2, 3, 4, 5, 6]

r1 = map(lambda x: x * x, list_x)
print(r1)  # 生成的是惰性的序列
print(list(r1))

r2 = map(lambda x, y: x + y, list_x, list_y)
print(r2)
print(list(r2))

map 和 reduce 组合 能非常简单地构建一个字符串转换成整数的方法 ->

from functools import reduce

DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}

def char2num(s):
    return DIGITS[s]

def str2int(s):
    return reduce(lambda x, y: x * 10 + y, map(char2num, s))

reduce

from functools import reduce

list_x = [1, 2, 3, 4, 5, 6, 7, 8]

r2 = reduce(lambda x, y: x + y, list_x)
print(r2)

reduce运算规则,连续计算,调用列表的第一个和第二个参数,通过传入的函数进行计算,返回值作为第一个参数,然后从列表读取第三个参数作为函数的第二个参数,再进行计算。。。直至参数调用结束。返回计算值。
二维数组的累加(累积计算,本处为相加)
reduce(func, param, initial) 函数、参数列表、初始值

from functools import reduce

move_list = [(1, 1), (-2, 1), (1, -3), (2, -4)]

result = reduce(lambda x, y: (x[0] + y[0], x[1] + y[1]), move_list, (10, 10))

print(result)

大数据计算模型: map/reduce
编程模型 map 映射 reduce 归约
大规模并行计算
借鉴思想:函数式编程

filter

过滤

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) # 构造新序列

判断列表字符是否大写,如果不是则去除,是则保留

list_u = ["a", "B", "c", "F", "e"]
re_d2 = filter(lambda s: s if s.isupper() else "", list_u)

print(list(re_d2))

命令式编程vs函数式编程

命令式编程:
func
条件判断
循环

函数式编程: # 理论上可以用map\reduce 替换所有 if..else... for
map
reduce
filter
lambda 算子

装饰器

更多的是一种设计模式

装饰器 二

import time

def time_dec(func):
    def func__(*args, **kw):
        print(time.time())
        return func(*args, **kw)
    return func__

@time_dec
def f1(name):
    print("This is a function" + name)

f1("name)

装饰器 三

语法糖 @funcname
采用了语法糖装饰函数,没带括号,已经运行了一层。
需要注意调用和引用的区别,需要注意调用次数和引用次数。
python装饰器大量应用了AOP的设计模式及思想:
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
https://baike.baidu.com/item/AOP/1332219?fr=aladdin

装饰器 四

非常经典的关于多重装饰器的装饰顺序,应该深入理解。

def decorator_a(func):
    print('Get in decorator_a')

    def inner_a(*args, **kwargs):
        print('Get in inner_a')
        return func(*args, **kwargs)

    return inner_a


def decorator_b(func):
    print('Get in decorator_b')

    def inner_b(*args, **kwargs):
        print('Get in inner_b')
        return func(*args, **kwargs)

    return inner_b


@decorator_b
@decorator_a
def f(x):
    print('Get in f')
    return x * 2
# 初始化的时候,先初始化a,a才能返回一个函数对象用于初始化b,否则没有对象给b去初始化。
# 初始化完成之后,返回的是一个b函数,调用b函数,才能返回a函数的调用从而完成整个装饰过程

f(1)

装饰器的传入参数,因为其通用性,需要传入可变参数:*args, **kwargs。。。

装饰器 五

加上关键字参数

装饰器 六

收尾
装饰器思想:
想对某一个被封装的单元修改某个功能,而不改变原代码。(开闭原则)
对功能拓展

哪些地方会用到:
flask
多重装饰

你可能感兴趣的:(11.函数式编程:匿名函数、高阶函数、装饰器)