一、面向过程
面向过程的编程思想
核心是过程二字:过程级流程,指的是解决问题先后先后顺序的步骤:先干啥,在干啥,接着干啥?
所以基于该思想编写程序就好比在设计一条流水线。
补充:无论哪种的编程范式设计出的程序, 最终的执行结果都是过程式的. 计算机底层的硬件的工作方式也是过程式的
优点:
降低程序程序的复杂度,将复杂的问题流程化,进而简单化
缺点:
程序的可拓展性极差,举例: 流水线的每道关卡都不可少, 不然影响整个流水线的运行.
面向过程的编程思想应用场景
前言
面向过程的编程思想一般用于功能一旦实现, 就很少需要改变的场景. 如果你要处理的任务是复杂的, 且现需要不断迭代更新和维护的, 那么面向过程的思想就不适用了.因此我们可以总结出以下两点:
-
不是所有的软件都需要频繁更迭: 编写脚本
-
即使一个软件需要频繁更迭, 也并代表这个软件所有的组成部分需要一起更迭: 登录注册的功能逻辑,
djongo
框架
二、编程范式
-
编程范式指的是编程的套路
-
主要的套路有三种:命令式编程, 函数式编程, 逻辑式编程
-
常见的面向对象就是命令式编程, 常见的面向过程就是逻辑式编程
三、函数式
什么是函数式?
-
函数式编程中的函数指的并不是编程语言中的函数(或方法)
-
它指的是数学意义上的函数,将计算机的运算视为数学意义上的运算,即映射关系(如:y = f(x)),就是 y 和 x 的对应关系
函数式与逻辑式
-
比起逻辑式,函数式更加注重的是执行结果并非执行的过程
-
面向过程就是逻辑式
-
函数式代表语言:
Hashell, Erlang
补充:python提供的函数式编程特性
-
Python并不是一门函数式的编程语言,但却提供了很多函数式编程的特性
-
比如 :
lambda, max, min, map, reduce, filter
四、匿名函数(lambda)
什么是匿名函数?
-
没有名字的函数
应用场景:
-
临时用一次,通常用于与其他函数配合使用
匿名函数的强调点
-
匿名函数的本质目的就是要没有名字,若给匿名函数赋值给一个名字事物没有意义的
-
匿名函数的参数规则、作用域关系与有名函数是一样的
-
匿名函数的函数体通常应该是一个表达式,该表达式必须要有一个返回值
匿名函数与有名函数对比
-
有名函数
# 有名函数,循环使用,保存了名字,通过名字就可以重复引用函数 def foo(x,y): return x**y foo(2,3)
-
匿名函数
#没有函数名,随时随地定义 f = lambda x,y:x ** y print(f(2,4)) # 16 # 一般配合应用 : max, min, sorted, map, reduce, filter
匿名函数的基本语法格式
lambda 参数1, 参数2, ..., 参数n: expression
匿名函数的调用方式
方式一:直接加括号就行
res = (lambda x, y: x + y)(7,8)
print(res) # 15
方式二:给函数指定名字
f = lambda x,y:x ** y
print(f(2,4)) # 16
# 匿名函数的本质就是没有名字,这里指定名字是没有意义的(匿名函数只用于临时调用一次)
# 匿名函数一般用来与其他函数配合使用,以下来展开介绍
五、匿名函数的应用
求最大值与最小值
1.max( ) : 最大值
-
接收两个参数 :
([可迭代对象],[函数])
-
注意:第二个参数函数,必须指定关键字形式:
key=匿名函数
2.min( ) : 最小值
-
接收两个参数 :
([可迭代对象],[函数])
-
注意:第二个参数函数,必须指定关键字形式:
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码进行比较. 如果是列表与列表之间的排序, 是以每个元素作为比较
-
接收三个参数 :
([可迭代对象],[函数],[排列顺序])
-
注意:第二个参数函数,必须指定关键字形式:
key=匿名函数
-
第三个参数是排序顺序(默认从小到大reverse=False). 指定从大到小: reverse=True
-
-
如果传入的可迭代对象是字典,默认是按照字典的
key
来进行排序的-
sorted 函数会迭代可迭代对象中的每个元素, 把迭代后得到的值依次传给匿名函数
-
如果是字典,那么迭代以后传给字典的就是 key, 最终,以匿名函数的返回值作为比较依据
-
比如传入的是字典, 默认迭代的就是字典的 key, 那么返回的只就是字典的 key, 虽然你是用 value来进行比较的
-
-
reverse参数 : “False”代表从小到大, “True”代表的是从大到小
#以每个人的薪资来做比较 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']
运行原理
sorted函数会迭代可迭代对象中的每个元素, 把迭代后得到的值依次传给匿名函数, 如果是字典,那么迭代以后传给字典的就是key。最终,以匿名函数的返回值作为比较依据.排序完毕以后会返回默认迭代可迭代对象的方式。比如: 字典默认迭代的就是key。那么他就会以key作为你的返回值,虽然你比较的依据是字典的value
。它的key是基于你value
的排序结果排序的key。
map( ) : 映射
-
接收两个参数 :
([函数],[可迭代对象])
-
运行原理: 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 中, 需要导入使用
-
运行原理 : 以初始值作为第一个参数传给 x , 然后迭代传入的可迭代对象, 拿到的值 y 与 x 相加重新赋值给 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)
filten( ) : 过滤
-
接收两个参数 :
([函数],[可迭代对象])
-
遍历可迭代对象, 过滤出结果为真的元素, 如果是字典, 最终返回的结果是字典的 key
-
filten 返回的结果是迭代器
示例
# 需求: 对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 = ()