07-09 面向过程与函数式

[TOC]

一 编程范式

? 很多初学者在了解了一门编程语言的基本语法和使用之后,面对一个’开发需求‘时仍然会觉得无从下手、没有思路/套路,本节主题“编程范式”正是为了解决该问题,那到底什么是编程范式呢?

编程范式指的就是编程的套路,打个比方,如果把编程的过程比喻为练习武功,那编程范式指的就是武林中的各种流派,而在编程的世界里常见的流派有:面向过程、函数式、面向对象等,本节我们主要介绍前两者。

? 在正式介绍前,我们需要强调:“功夫的流派没有高低之分,只有习武的人才有高低之分“,在编程世界里更是这样,各种编程范式在不同的场景下都各有优劣,谁好谁坏不能一概而论,下面就让我们来一一解读它们。

插图:恶搞图62

二 面向过程

? ”面向过程“核心是“过程”二字,“过程”指的是解决问题的步骤,即先干什么再干什么......,基于面向过程开发程序就好比在设计一条流水线,是一种机械式的思维方式,这正好契合计算机的运行原理:任何程序的执行最终都需要转换成cpu的指令流水按过程调度执行,即无论采用什么语言、无论依据何种编程范式设计出的程序,最终的执行都是过程式的。

插图:恶搞图63

? 详细的,若程序一开始是要着手解决一个大的问题,按照过程式的思路就是把这个大的问题分解成很多个小问题或子过程去实现,然后依次调用即可,这极大地降低了程序的复杂度。举例如下:

? 写一个数据远程备份程序,分三步:本地数据打包,上传至云服务器,检测备份文件可用性

import os,time

# 一:基于本章所学,我们可以用函数去实现这一个个的步骤
# 1、本地数据打包
def data_backup(folder):
    print("找到备份目录: %s" %folder)
    print(‘正在备份...‘)
    zip_file=‘/tmp/backup_%s.zip‘ %time.strftime(‘%Y%m%d‘)
    print(‘备份成功,备份文件为: %s‘ %zip_file)
    return zip_file

# 2、上传至云服务器
def cloud_upload(file):
    print("\nconnecting cloud storage center...")
    print("cloud storage connected")
    print("upload [%s] to cloud..." %file)
    link=‘https://www.xxx.com/bak/%s‘ %os.path.basename(file)
    print(‘close connection‘)
    return link

#3、检测备份文件可用性
def data_backup_check(link):
    print("\n下载文件: %s , 验证文件是否无损..." %link)

# 二:依次调用
# 步骤一:本地数据打包
zip_file = data_backup(r"/Users/egon/欧美100G高清无码")

# 步骤二:上传至云服务器
link=cloud_upload(zip_file)

# 步骤三:检测备份文件的可用性
data_backup_check(link)

插图:恶搞图64

面向过程总结:

1、优点

将复杂的问题流程化,进而简单化

2、缺点

‘‘‘
程序的可扩展性极差,因为一套流水线或者流程就是用来解决一个问题,就好比生产汽水的流水线无法生产汽车一样,即便是能,也得是大改,而且改一个组件,与其相关的组件可能都需要修改,比如我们修改了cloud_upload的逻辑,那么依赖其结果才能正常执行的data_backup_check也需要修改,这就造成了连锁反应,而且这一问题会随着程序规模的增大而变得越发的糟糕。
‘‘‘

def cloud_upload(file): # 加上异常处理,在出现异常的情况下,没有link返回
    try:
        print("\nconnecting cloud storage center...")
        print("cloud storage connected")
        print("upload [%s] to cloud..." %file)
        link=‘https://www.xxx.com/bak/%s‘ %os.path.basename(file)
        print(‘close connection‘)
        return link
    except Exception:
        print(‘upload error‘)
    finally:
        print(‘close connection.....‘)

def data_backup_check(link): # 加上对参数link的判断
    if link:
        print("\n下载文件: %s , 验证文件是否无损..." %link)
    else:
        print(‘\n链接不存在‘)

3、应用场景

面向过程的程序设计一般用于那些功能一旦实现之后就很少需要改变的场景, 如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程去实现是极好的,但如果你要处理的任务是复杂的,且需要不断迭代和维护, 那还是用面向对象最为方便。

插图:恶搞图65

三 函数式

函数式编程并非用函数编程这么简单,而是将计算机的运算视为数学意义上的运算,比起面向过程,函数式更加注重的是执行结果而非执行的过程,代表语言有:Haskell、Erlang。而python并不是一门函数式编程语言,但是仍为我们提供了很多函数式编程好的特性,如lambda,map,reduce,filter

插图:恶搞图66

3.1 匿名函数与lambda

? 对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下

lambda 参数1,参数2,...: expression

举例

# 1、定义
lambda x,y,z:x+y+z

#等同于
def func(x,y,z):
    return x+y+z

# 2、调用
# 方式一:
res=(lambda x,y,z:x+y+z)(1,2,3)

# 方式二:
func=lambda x,y,z:x+y+z # “匿名”的本质就是要没有名字,所以此处为匿名函数指定名字是没有意义的
res=func(1,2,3)

插图:恶搞图67

匿名函数与有名函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,所以匿名函数用于临时使用一次的场景,匿名函数通常与其他函数配合使用,我们以下述字典为例来介绍它

salaries={
    ‘siry‘:3000,
    ‘tom‘:7000,
    ‘lili‘:10000,
    ‘jack‘:2000
}

要想取得薪水的最大值和最小值,我们可以使用内置函数max和min(为了方便开发,python解释器已经为我们定义好了一系列常用的功能,称之为内置的函数,我们只需要拿来使用即可)

>>> max(salaries)
‘tom‘
>>> min(salaries)
‘jack‘

内置max和min都支持迭代器协议,工作原理都是迭代字典,取得是字典的键,因而比较的是键的最大和最小值,而我们想要的是比较值的最大值与最小值,于是做出如下改动

# 函数max会迭代字典salaries,每取出一个“人名”就会当做参数传给指定的匿名函数,然后将匿名函数的返回值当做比较依据,最终返回薪资最高的那个人的名字
>>> max(salaries,key=lambda k:salaries[k])
‘lili‘
# 原理同上
>>> min(salaries,key=lambda k:salaries[k])
‘jack‘

同理,我们直接对字典进行排序,默认也是按照字典的键去排序的

>>> sorted(salaries)
[‘jack‘, ‘lili‘, ‘siry‘, ‘tom‘]

插图:恶搞图68

3.2 map、reduce、filter

函数map、reduce、filter都支持迭代器协议,用来处理可迭代对象,我们以一个可迭代对象array为例来介绍它们三个的用法

array=[1,2,3,4,5]

要求一:对array的每个元素做平方处理,可以使用map函数

map函数可以接收两个参数,一个是函数,另外一个是可迭代对象,具体用法如下

>>> res=map(lambda x:x**2,array)
>>> res
<map object at 0x1033f45f8>
>>> 

解析:map会依次迭代array,得到的值依次传给匿名函数(也可以是有名函数),而map函数得到的结果仍然是迭代器。

>>> list(res) #使用list可以依次迭代res,取得的值作为列表元素
[1, 4, 9, 16, 25]

插图:恶搞图69

要求二:对array进行合并操作,比如求和运算,这就用到了reduce函数

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

# reduce在python2中是内置函数,在python3中则被集成到模块functools中,需要导入才能使用
>>> from functools import reduce
>>> res=reduce(lambda x,y:x+y,array)
>>> res
15

解析:

1 没有初始值,reduce函数会先迭代一次array得到的值作为初始值,作为第一个值数传给x,然后继续迭代一次array得到的值作为第二个值传给y,运算的结果为3

2 将上一次reduce运算的结果作为第一个值传给x,然后迭代一次array得到的结果作为第二个值传给y,依次类推,知道迭代完array的所有元素,得到最终的结果15

也可以为reduce指定初始值

>>> res=reduce(lambda x,y:x+y,array,100)?>>> res
115

要求三:对array进行过滤操作,这就用到了filter函数,比如过滤出大于3的元素

>>> res=filter(lambda x:x>3,array)

解析:filter函数会依次迭代array,得到的值依次传给匿名函数,如果匿名函数的返回值为真,则过滤出该元素,而filter函数得到的结果仍然是迭代器。

>>> list(res)
[4, 5]

提示:我们介绍map、filter、reduce只是为了带大家了解函数式编程的大致思想,在实际开发中,我们完全可以用列表生成式或者生成器表达式来实现三者的功能。

插图:恶搞图70

原文地址:https://blog.51cto.com/egon09/2461941

时间: 2024-11-05 15:50:30

07-09 面向过程与函数式的相关文章

python面向过程与函数式编程

周六闲暇的午后,看到博客园众多大神的技术贴.作为一个什么都不懂的小学生,也开通了自己的博客,以后可以对外装×成伪大神了.第一篇记录下今天下午学的python基础: 1.面向过程编程:在python中,所说的过程其实和函数差别不大,也需要def进行定义,但是过程是没有返回值的. def guocheng(): print('我是过程') 上面定义的就是一个过程,没有返回值,只有函数内部的相关逻辑. 调用上面的过程:a=guocheng(),这样即可调用,如果在面板上打印a,会显示NONE,因为过程

面向过程,面向对象,函数式对同一个问题的思考方式

我之所以对函数式代码感兴趣是因为函数式代码富有表现力,可以使用简短.紧凑的代码完成工作,同时能对特定的问题给出优雅的解决方案.现代的编程语言不约而同的朝着面向对象.函数式.动态.解释执行的方向发展,例如Ruby,Swift.而另一些语言则更加强调函数式编程,如F#,Scala,这种语言有着强大的类型推断系统,编写的代码洁程度则令人叹为观止. 在F#编写一个两个数相加的函数,在F# Interactive中输入: let add num1 num2=num1*num2;; F# Interacti

函数式、面向过程、面向对象

面向过程: 1.搜索目标 2.表白 3.恋爱 4.见家长 5结婚 函数式编程: def cal(x): return x*2 + 1 a.不可变,不用变量保存状态,不修改变量 非函数式 a=1 def inc(): global a a+=1  #有改值 return a b.第一类对象:函数对"变量" 函数名可以当做参数传递 返回值可以是函数名 原文地址:https://www.cnblogs.com/wrw202/p/9589570.html

渐进式编码规范,一步步从面向过程到面向对象

学习js这么久了,一步步见证着自己的成长,看到别的大牛的代码,一步步去完善自己,今天,我就来通过一个简单的实例来记录自己的进步. 通过输入框输入字符串,来显示输入的字符数量. 1.函数式编程(初出新手村)不建议使用 //面向过程的变成方式,不推荐 window.onload=function(){ var $=function(id){ return document.getElementById(id); }; var oInput=$("input_word"); var getN

面向对象和面向过程的编程方式的理解

面向对象和面向过程的区别? 如果说面向对象和面向过程的具体区别,最深入的地方应该是去看设计模式,推荐大话设计模式那本书,讲的比较好.本人只不过简单叙述下,重点是如何进行面向对象和面向过程的编程,只有会编程了,才能真正懂得面向对象和面向过程的区别.否则都是纸上谈兵. 面向过程:是以计算机线性思维的方式进行编程.一步一个脚印的执行.本身也没有问题,但是如果遇到需求多变的情况,或者功能的添加和删除,将极其影响原来的程序代码,必须要重写或者修改,或者重新组织原来的代码. 面向对象:在对需求多变的时候,不

Python之面向过程和面向对象的区别

一.面向过程 1.面向过程:核心是过程二字,过程指的是解决问题的步骤,好比如设计一条流水线,是一种机械式的思维方式. 就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题 .基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决. 2.优缺点:  优点:将复杂的问题流程化,进而简单化.  缺点:扩展性差 3.实例:面向过程式的登录注册程序 import json,re

Python面向过程和面向对象基础

总结一下: 面向过程编程:根据业务逻辑从上到下的写代码-----就是一个project写到底,重复利用性比较差 函数式:将某些特定功能代码封装到函数中------方便日后调用 面向对象:对函数进行分类封装,使开发更快捷更灵活 面向过程编程: 1 name = "mac" 2 age = 15 3 sex = 'male' 4 #...... 5 print("%s's %s,%d years old!" %(name,sex,age)) 函数式: 1 def nam

类与对象 面向对象和面向过程对比 面向对象三大特征:封装 继承 多态

 初识面向对象 面向过程: 一切以事务的发展流程为中心. 面向对象: 一切以对象为中心. 一切皆为对象. 具体的某一个事务就是对象 打比方: 大象进冰箱 步骤: 第一步, 开门, 第二步, 装大象, 第三步, 关门 面向对象:大象, 你进冰箱. 此时主语是大象. 我操纵的是大象. 此时的大象就是对象 1. 面向过程: 一切以事物的流程为核心. 核心是"过程"二字, 过程是指解决问题的步骤, 即, 先?干什么, 后干什么. 基于该思想编写程序就好比在编写一套流水线. 是一种机械 式的编程

Python 面向对象和面向过程对比

# 大象装冰箱 # 脚本, 此时代码是最简单的. 不需要构思整个程序的概况 print("开门") print("装大象") print("关门") # 函数式编程. 比脚本麻烦. 对功能有了概况. def kai(): print('开门') def zhuang(): print("装大象") def guan(): print('关门') kai() zhuang() guan() # 面向对象编程, 对整个系统进行分析