06-10 面向过程与函数式

一. 编程范式

"""
什么是编程范式?
	指的就是编程的套路.
	主要的3种编程套路: 面向过程, 函数式, 面向对象
"""

二. 面向过程

"""
# 面向过程的编程思想:
	"过程"(核心): 过程即流程, 指的是解决问题先后顺序的步骤: 先干什么? 后干什么,接着干什么? 
	基于该思想编写程序就好比在设计一条流水线。
	补充: 无论哪种的编程范式设计出的程序, 最终的执行结果都是过程式的. 计算机底层的硬件的工作方式也是过程式的.

	优点: 降低程序的复杂度, 将复杂的问题流程化, 进而简单化
	缺点: 程序的可扩展性极差. 举例: 流水线的每道关卡都不可少, 不然影响整个流水线的运行.

# 面向过程的编程思想应用场景分析: 
	前言: 面向过程的编程思想一般用于功能一旦实现, 就很少需要改变的场景. 如果你要处理的任务是复杂的, 且现需要不断迭代更新和维护的, 那么面向过程的思想就不适用了.因此我们可以总结出以下两点:
	1. 不是所有的软件都需要频繁更迭: 编写脚本
	2. 即使一个软件需要频繁更迭, 也并代表这个软件所有的组成部分需要一起更迭: 登录注册的功能逻辑, djongo框架
"""

三. 函数式

"""
# 什么是函数式编程?
	函数式编程并非函数编程这么简单, 而是将计算机的运算视为数学意义上的运算.

# 函数式编程与面向过程:
	 比起面向过程, 函数式更加注重的是执行结果而非执行的过程.
	
# 函数式代表语言: Hashell, Erlang

补充: python并不是一门函数式编程语言, 但是仍然提供了很多函数式编程的好特性.如:lambda,  max, min, map, reduce, filter
"""

1. 匿名函数lambda

  • lambda函数基本介绍
"""
匿名函数语法:
	lambda 参数1, 参数2, ..., 参数n: expression
"""
# 一. 有名函数与匿名函数介绍:
# 1. def用来定义有名函数。
# def=函数的内存地址
def func(x, y, z):
    return x + y + z
print(func)  # <function func at 0x00000290E7F8CE50>

# 2. lambda用于定义匿名函数。
print(lambda x, y, z: x + y + z)  # <function <lambda> at 0x00000290E7F8CEE0>

'''
由上面def定义的有名函数和定义的匿名函数,通过打印可以看到有名函数。打印的结果, 由名字映射的都是一个内存地址,而匿名函数打印的结果也是一个内存地址。那么既然他们两个都是一个内存地址,那么下面我们加过号都可以进行调用。所以我们匿名函数有两种调用的方式。方式如下:
'''
# 二. 匿名函数的两种调用方式:
# 1. 方式一: 
res = (lambda x, y, z: x + y + z)(1, 2, 3)
print(res)  # 6

# 2. 方式二: 
func = lambda x, y, z: x + y + z
res = func(1, 2, 3)
print(res)  # 6

# 匿名函数小结: 匿名本质就是没有名字, 这里为匿名函数指定名字是没有实际意义的.匿名函数只是用于临时调用一次的场景, 而更多的是将匿名函数与其他函数配合使用。

2. max与min 求最大值 最小值

"""
max与min接收2个参数: 
	第一个参数是可迭代对象. 
	第二个参数是函数. 必须指定关键字形式: key=匿名函数
		不指定参数: 使用默认方式迭代比较.( 如果迭代的对象是字典, 那么默认迭代方式的是字典的key, 由key作为本次函数的比较依据。)
		指定参数: max与min会把迭代完毕以后的结果作为参数传给函数, 如果迭代的对象是字典,那么就会把字典迭代之后的结果。也就是字典的key当做参数。传给lambda函数赋值给定义的参数。然后以返回值作为比较依据	
"""
# 需求: 获取最大薪资或者最小薪资的那个人
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}

# 函数max会迭代字典salaries, 迭代字典默认取出的key会当作参数传给指定的匿名函数.
# 比较依据: 将函数的返回值 salaries[k] 返回, 作为比较依据
# 返回结果: 将比较完毕以后的的参数k当作返回值
res = max(salaries, key=lambda k: salaries[k])
print(res)  # lili

res = min(salaries, key=lambda k: salaries[k])
print(res)  # jack

3. sorted 排序 (默认升序)

'''
注意: 只能用于同种类型的数据排序, 除了整型和字符串类型. 如果是字符串排序, 是以每个字符之间对应的ASCII码进行比较. 如果是列表与列表之间的排序, 是以每个元素作为比较.

sorted接收3个参数: 
	第一个参数是可迭代对象.
	第二个参数是函数. 必须指定关键字形式: key=匿名函数. 
	第三个参数是排序顺序(默认从小到大reverse=False). 指定从大到小: reverse=True

运行原理:
	sorted函数会迭代可迭代对象中的每个元素, 把迭代后得到的值依次传给匿名函数, 如果是字典,那么迭代以后传给字典的就是key。最终,以匿名函数的返回值作为比较依据.排序完毕以后会返回默认迭代可迭代对象的方式。比如: 字典默认迭代的就是key。那么他就会以key作为你的返回值,虽然你比较的依据是字典的value。它的key是基于你value的排序结果排序的key。
'''
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}
# 默认是按照字典的key进行排序的.
res = sorted(salaries)
print(res)  # ['jack', 'lili', 'siry', 'tom'] -- > 字符串比较按照ASCII码比较: 'j'(106) < 'l'(108) < 's'(115) < 't'(116)

# 需求: 按照薪资从小到大排序(默认升序 reverse=False)
res = sorted(salaries, key=lambda k: salaries[k])
# res = sorted(salaries, key=lambda k: salaries[k], reverse=False)
print(res)  # ['jack', 'siry', 'tom', 'lili']

# 需求: 按照薪资从大到小排序(reverse=True)
res = sorted(salaries, key=lambda k: salaries[k], reverse=True)
print(res)  # ['jack', 'siry', 'tom', 'lili']

4. map映射, reduce合并, filter过滤

  • map 映射 (注意: map得到的结果是迭代器对象)
'''
map接收2个参数: 
	第一个参数是函数
	第二个参数是可迭代对象

运行原理:
	map函数会迭代你指定的可迭代对象中的每个元素, 把迭代得到的值当做参数传给匿名函数, 以返回值的处理结果当做返回值返回.(注意: map得到的结果是迭代器对象)
'''
# 需求: 将array的每个元素做平方处理
array = [1, 2, 3, 4, 5]
res = map(lambda item: item ** 2, array)
print(res)  # map得到的结果是迭代器对象. 返回结果: <map object at 0x00000176D87AFDF0>
print(list(res))  # [1, 4, 9, 16, 25]

# map的替代方案: 使用生成器表达式
res = (item ** 2 for item in array)
print(res)  # <generator object <genexpr> at 0x0000022EA48343C0>
print(list(res))  # [1, 4, 9, 16, 25]
  • reduce 合并
"""	
使用方法: 
    reduce在python2中是内置函数, 在python3中被集成到模块functools中, 需要导入使用

reduce接收三个参数:
	第一个参数是函数
	第二个参数是可迭代对象
	第三个参数是初始值

运行原理:
    没有指定初始值: reduce函数会迭代一次你指定的可迭代对象, 得到的值作为初始值, 作为第一个参数传给x, 然后继续迭代你指定的可迭代对象, 得到的第二个值传给y. x只在初始阶段被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
    有指定初始值: reduce函数会将指定的值作为初始值, 作为第一个参数传给x, 继续迭代你指定的可迭代对象, 得到的第二个值传给y. x只在初始阶段被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
"""
# 需求: 对array进行合并求和运算
from functools import reduce
array = [1, 4, 9, 16, 25]
res = reduce(lambda x, y: x + y, array, 0)
print(res)  # 55

# reduce的替代方案: sum
print(sum(array))  # 55

# reduce的替代方案: 使用生成器表达式 + sum
salaries = {
    'siry': 3000,
    'tom': 7000,
    'lili': 10000,
    'jack': 2000
}
res = sum(value for value in salaries.values())
print(res)  # 22000

# 验证(重点理解): 保留x的状态, 将每次y的值与x进行操作, 直至结束
li = [1, '2', '3', '4']
res = reduce(lambda x, y: x + y if isinstance(y, int) else x + int(y), li)
print(res)  # 10

# 注意: x在初始阶段只被赋值一次, 并保留x的状态, 将每次y的值与x进行操作, 直至结束.
# (((10 - 1) - 2) - 3) = 4
res = reduce(lambda x, y: x - y, [1, 2, 3], 10)
print(res)

# ((1 - 2) - 3) = -4 
res = reduce(lambda x, y: x - y, [1, 2, 3])
print(res)
  • filter 过滤(注意: filter返回的结果是迭代器)
'''
filter接收2个参数:
	第一个参数是函数
	第二个参数是可迭代对象
	
运行原理
	filter函数会依次迭代你指定的可迭代对象, 得到的值当实参依次传给匿名函数, 如果匿名函数的返回值为真, 则过滤出该元素. filter返回值是默认遍历完毕以后的对象。如果你是一个字典,默认遍历的是key。那么就算你过滤了以后,你返回的对象也是以key为主, 这个时候你使用list转换。list中元素就是刚刚遍历的字典的key。(注意: filter返回的结果是迭代器)
'''
# 需求: 对array进行过滤取出大于3小于16的数
array = [1, 4, 9, 16, 25]
res = filter(lambda item: 16 > item > 3 , array)
print(res)  # <filter object at 0x000001A219BEFDF0>

print(list(res))  # [4, 9]

# filter的替代方案: 使用生成器表达式
res = ()
posted @ 2020-03-26 21:10  给你加马桶唱疏通  阅读(155)  评论(0编辑  收藏  举报