一、面向过程编导思想
编程思想/范式
面向过程的编程思想:
核心是"过程"二字,过程即流程,指的是做事的步骤:先什么、再什么、后干什么
基于该思想编写程序就好比在设计一条流水线
优点:复杂的问题流程化、进而简单化
缺点:扩展性非常差
面向过程的编程思想应用场景解析:
1、不是所有的软件都需要频繁更迭:比如编写脚本
2、即便是一个软件需要频繁更迭,也不并不代表这个软件所有的组成部分都需要一起更迭
二、匿名函数
匿名函数与lambda
对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下
lambda 参数1,参数2,...: expression
def用于定义有名函数
func=函数的内存地址
def func(x,y):
return x+y
print(func)
lamdab用于定义匿名函数
print(lambda x,y:x+y)
调用匿名函数
方式一:
res=(lambda x,y:x+y)(1,2)
print(res)
方式二:
func=lambda x,y:x+y
res=func(1,2)
print(res)
匿名用于临时调用一次的场景:更多的是将匿名与其他函数配合使用
匿名函数的应用
匿名函数与有名函数有相同的作用域,但是匿名意味着引用计数为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']
了解:map、reduce、filter应用
要求一:对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]
要求二:对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只是为了带大家了解函数式编程的大致思想,在实际开发中,
我们完全可以用列表生成式或者生成器表达式来实现三者的功能。
模块
1、什么是模块?
模块就是一系列功能的集合体,分为三大类
I:内置的模块
II:第三方的模块
III:自定义的模块
一个python文件本身就一个模块,文件名m.py,模块名叫m
ps:模块有四种形式
1 使用python编写的.py文件
2 已被编译为共享库或DLL的C或C++扩展
3 把一系列模块组织到一起的文件夹(注:文件夹下有一个__init__.py文件,该文件夹称之为包)
4 使用C编写并链接到python解释器的内置模块
2、为何有用模块
I:内置与第三的模块拿来就用,无需定义,这种拿来主义,可以极大地提升自己的开发效率
II:自定义的模块
可以将程序的各部分功能提取出来放到一模块中为大家共享使用
好处是减少了代码冗余,程序组织结构更加清晰
3、如何用模块
import语句
有如下示范文件
#文件名:foo.py
x=1
def get():
print(x)
def change():
global x
x=0
class Foo:
def func(self):
print('from the func')
要想在另外一个py文件中引用foo.py中的功能,需要使用import foo,首次导入模块会做三件事:
1、执行源文件代码
2、产生一个新的名称空间用于存放源文件执行过程中产生的名字
3、在当前执行文件所在的名称空间中得到一个名字foo,该名字指向新创建的模块名称空间,若要引用模块名称空间中的名字,
需要加上该前缀,如下
import foo #导入模块foo
a=foo.x #引用模块foo中变量x的值赋值给当前名称空间中的名字a
foo.get() #调用模块foo的get函数
foo.change() #调用模块foo中的change函数
obj=foo.Foo() #使用模块foo的类Foo来实例化,进一步可以执行obj.func()
加上foo.作为前缀就相当于指名道姓地说明要引用foo名称空间中的名字,所以肯定不会与当前执行文件所在名称空间中的名字相冲突,
并且若当前执行文件的名称空间中存在x,执行foo.get()或foo.change()操作的都是源文件中的全局变量x。
需要强调一点是,第一次导入模块已经将其加载到内存空间了,之后的重复导入会直接引用内存中已存在的模块,
不会重复执行文件,通过 import sys,打印sys.modules的值可以看到内存中已经加载的模块名。
提示:
#1、在Python中模块也属于第一类对象,可以进行赋值、以数据形式传递以及作为容器类型的元素等操作。
#2、模块名应该遵循小写形式,标准库从python2过渡到python3做出了很多这类调整,比如ConfigParser、Queue、
SocketServer全更新为纯小写形式。
用import语句导入多个模块,可以写多行import语句
import module1
import module2
...
import moduleN
还可以在一行导入,用逗号分隔开不同的模块
import module1,module2,...,moduleN
但其实第一种形式更为规范,可读性更强,推荐使用,而且我们导入的模块中可能包含有python内置的模块、
第三方的模块、自定义的模块,为了便于明显地区分它们,我们通常在文件的开头导入模块,并且分类导入,
一类模块的导入与另外一类的 导入用空行隔开,不同类别的导入顺序如下:
#1. python内置模块
#2. 第三方模块
#3. 程序员自定义模块
当然,我们也可以在函数内导入模块,对比在文件开头导入模块属于全局作用域,在函数内导入的模块则属于局部的作用域。
自定义模块的命名应该采用纯小写+下划线的风格
可以在函数内导入模块
def func():
import foo