面向过程的编程思想,核心是“过程”二字,过程即流程,指的是做事的步骤,即先干什么、再干什么、后干什么。
基于面向过程开发程序就好比在设计一条流水线,是一种机械式的思维方式。这正好契合计算机的运行原理:任何程序的执行最终都需要转换成CPU的指令,按过程调度执行。即无论采用什么语言、无论依据何种编程范式设计出的程序,最终的执行都是过程式的。
编程范式指的就是编程的套路,打个比方,如果把编程的过程比喻为练习武功,那编程范式指的就是武林中的各种流派,而在编程的世界里常见的流派有:面向过程、函数式、面向对象等。
优点:复杂的问题流程化、进而简单化
缺点:扩展性非常差
面向过程的程序设计一般用于那些功能一旦实现之后就很少需要改变的场景, 如果只是写一些简单的脚本,去做一些一次性任务,用面向过程去实现是极好的。但如果要处理的任务是复杂的,且需要不断迭代和维护, 那还是用面向对象最为方便。
函数式编程并非用函数编程这么简单,而是将计算机的运算视为数学意义上的运算。比起面向过程,函数式更加注重的是执行结果而非执行的过程,代表语言有:Haskell、Erlang。而Python并不是一门函数式编程语言,但是仍为我们提供了一些函数式编程的特性,如lambda,map,reduce,filter
func=函数的内存地址
def func(x,y):
return x+y
print(func)
对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下:
lambda 参数1,参数2,...: 返回值
lambda x, y: x + y
res = (lambda x, y: x + y)(1, 2)
print(res) # 3
func = lambda x, y: x + y
res = func(1, 2)
print(res) # 3
# 匿名函数的特点在于本来就没有名字,这么做给它套了个名字好像显得有点多余
匿名,意味着造出来的是一个函数的内存地址,这个内存地址没有捆绑任何名字,所以它在定义完的下一刻就会被垃圾回收机制回收。也就是说,它的价值就只在它被制造出来的那一刻。
匿名函数用于临时调用一次的场景,更多的是将匿名函数与其他函数配合使用。
salaries={
'siry':3000,
'tom':7000,
'lili':10000,
'jack':2000
}
要想取得薪水的最大值和最小值,我们可以使用内置函数max和min(为了方便开发,python解释器已经为我们定义好了一系列常用的功能,称之为内置的函数,我们只需要拿来使用即可)
salaries = {
'siry': 3000,
'tom': 7000,
'lili': 10000,
'jack': 2000
}
print(max(salaries)) # tom
print(min(salaries)) # jack
内置max和min都支持迭代器协议,迭代的内容是啥,返回的就是啥。这里的工作原理是迭代字典,取得是字典的键,因而比较的是键的最大和最小值。我们唯一能做的事情就是让max和min不要用迭代出来的内容当做比较依据,而用key参数指定的值当做比较依据。
而我们想要的是比较值的最大值与最小值,该怎么办?
def func(k):
return salaries[k]
res = max(salaries, key=func)
# max函数的key参数用来指定比较的依据,通常是被赋一个函数的内存地址。
# max每次会把从salaries中迭代出的内容,传给key所指定的func函数当做参数,继而把func函数以此参数得到的返回值当做比较依据。
print(res)
要注意的是:比较依据虽然发生了变化,但max的返回值(结果)仍是从salaries中迭代出来的内容。
salaries = {
'siry': 3000,
'tom': 7000,
'lili': 10000,
'jack': 2000
}
res = max(salaries, key=lambda k: salaries[k])
print(res) # lili
以上,我们通过匿名函数的方法让代码变得更加简洁,且不丧失可读性。
按照max的例子,我们可以写出min的实现代码:
res = min(salaries, key=lambda k: salaries[k])
print(res)
甚至是使用sorted来进行排序:
salaries = {
'siry': 3000,
'tom': 7000,
'lili': 10000,
'jack': 2000
}
res = sorted(salaries, key=lambda k: salaries[k], reverse=True) # reverse = True 代表排序规则是由大到小
print(res) # ['lili', 'tom', 'siry', 'jack']
map()可以接收两个参数,一个是函数,另外一个是可迭代对象。
我们想用一个新列表(new_l)来映射一个旧列表(l),new_l中的每一个元素都是与l相对应位置的元素再添加“老师”后缀,该怎么做?
使用列表生成器:
l = ['siry', 'tom', 'lili', 'jack']
new_l = [name + '老师' for name in l]
print(new_l) # ['siry老师', 'tom老师', 'lili老师', 'jack老师']
使用map:
l = ['siry', 'tom', 'lili', 'jack']
# map会依次迭代l,得到的值依次传给匿名函数
new_l = map(lambda name: name + '老师', l)
print(new_l) #
# 要注意:使用map得到的结果仍然是一个迭代器。
res = list(new_l) # 使用list可以依次迭代new_l,取得的值作为列表元素
print(res) # ['siry老师', 'tom老师', 'lili老师', 'jack老师']
对new_l进行过滤操作,这就用到了filter函数,比如过滤出以“老师”后缀结尾的元素。
使用列表生成器:
new_l = ['siry老师', 'tom老师', 'lili老师', 'jack老师', '混入其中的山炮']
res = [name for name in new_l if name.endswith('老师')]
print(res) # ['siry老师', 'tom老师', 'lili老师', 'jack老师']
# 如果列表元素过多该怎么办? ==》使用生成器表达式,再通过list依次迭代入列表
res = (name for name in new_l if name.endswith('老师'))
print(list(res)) # ['siry老师', 'tom老师', 'lili老师', 'jack老师']
使用filter:
new_l = ['siry老师', 'tom老师', 'lili老师', 'jack老师', '混入其中的山炮']
res = filter(lambda name: name.endswith('老师'), new_l)
print(res) # 结果是一个迭代器