python基础4
------------恢复内容开始------------
面向过程与函数式
编程范式指的就是编程的套路,各种编程范式在不同的场景 下都各有优劣。
面向过程
‘面向过程’核心是‘过程’二字,‘过程’指的是解决问题的步骤,即先干什么再干什么,基于面向过程开发程序就好比在设计一条流水线,是一种机械式的思维方式,这正好契合计算机的运行原理:任何程序的执行最终都需要转换成cpu的指令流水按过程调度执行,即无论采用什么语言、无论依据何种编程范式设计出的程序,最终的执行都是过程式的。
优点:将复杂的问题流程化,进而简单化
缺点:程序的可扩展性极差,因为一套流水线或者流程就是用来解决一个问题
函数式
1、匿名函数与lambda
对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数
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)
max,min为内置函数,取最大,取小值
map、reduce、filter
map函数可以接收两个参数,一个是函数,另外一个是可迭代对象,具体用法如下
>>> res=map(lambda x:x**2,array) >>> res <map object at 0x1033f45f8> >>>
比如求和运算,这就用到了reduce函数
reduce函数可以接收三个参数,一个是函数,第二个是可迭代对象,第三个是初始值
# reduce在python2中是内置函数,在python3中则被集成到模块functools中,需要导入才能使用 >>> from functools import reduce >>> res=reduce(lambda x,y:x+y,array) >>> res 15
过滤操作,这就用到了filter函数,比如过滤出大于3的元素
res=filter(lambda x:x>3,array)
模块
将程序模块化会使得程序的组织结构清晰,维护起来更加方便。比起直接开发一个完整的程序,单独开发一个小的模块也会更加简单,并且程序中的模块与电脑中的零部件稍微不同的是:程序中的模块可以被重复使用。所以总结下来,使用模块既保证了代码的重用性,又增强了程序的结构性和可维护性。另外除了自定义模块外,我们还可以导入使用内置或第三方模块提供的现成功能,这种“拿来主义”极大地提高了程序员的开发效率。
模块的使用
1、import语句
要想在另外一个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()
用import语句导入多个模块,可以写多行import语句
import module1
import module2
...
import moduleN
还可以在一行导入,用逗号分隔开不同的模块
import module1,module2,...,moduleN
但其实第一种形式更为规范,可读性更强,推荐使用
#1. python内置模块 #2. 第三方模块 #3. 程序员自定义模块
from-import 语句
from...import...与import语句基本一致,唯一不同的是
:使用import foo导入模块后,引用模块中的名字都需要加上foo.作为前缀,
而使用from foo import x,get,change,Foo则可以在当前执行文件中直接引用模块foo中的名字
from foo import x,get,change #将模块foo中的x和get导入到当前名称空间 a=x #直接使用模块foo中的x赋值给a get() #直接执行foo中的get函数 change() #即便是当前有重名的x,修改的仍然是源文件中的x
如果我们需要引用模块中的名字过多的话,可以采用上述的导入形式来达到节省代码量的效果,但是需要强调的一点是:只能在模块最顶层使用的方式导入,在函数内则非法,并且的方式会带来一种副作用,即我们无法搞清楚究竟从源文件中导入了哪些名字到当前位置,这极有可能与当前位置的名字产生冲突。模块的编写者可以在自己的文件中定义__all__变量用来控制*代表的意思
模块部分详情参考https://zhuanlan.zhihu.com/p/109127048
循环导入问题
循环导入问题指的是在一个模块加载/导入的过程中导入另外一个模块,而在另外一个模块中又返回来导入第一个模块中的名字,由于第一个模块尚未加载完毕,所以引用失败、抛出异常,究其根源就是在python中,同一个模块只会在第一次导入时执行其内部代码,再次导入该模块时,即便是该模块尚未完全加载完毕也不会去重复执行内部代码
解决方案
# 方案一:导入语句放到最后,保证在导入时,所有名字都已经加载过 # 文件:m1.py print('正在导入m1') x='m1' from m2 import y # 文件:m2.py print('正在导入m2') y='m2' from m1 import x # 文件:run.py内容如下,执行该文件,可以正常使用 import m1 print(m1.x) print(m1.y) # 方案二:导入语句放到函数中,只有在调用函数时才会执行其内部代码 # 文件:m1.py print('正在导入m1') def f1(): from m2 import y print(x,y) x = 'm1' # 文件:m2.py print('正在导入m2') def f2(): from m1 import x print(x,y) y = 'm2' # 文件:run.py内容如下,执行该文件,可以正常使用 import m1 m1.f1()
搜索模块的路径与优先级
1、使用纯Python代码编写的py文件
2、包含一系列模块的包
3、使用C编写并链接到Python解释器中的内置模块
4、使用C或C++编译的扩展模块
区分py文件的两种用途
一个Python文件有两种用途,一种被当主程序/脚本执行,另一种被当模块导入,为了区别同一个文件的不同用途,每个py文件都内置了__name__变量,该变量在py文件被当做脚本执行时赋值为“__main__”,在py文件被当做模块导入时赋值为模块名
编写一个规范的模块
我们在编写py文件时,需要时刻提醒自己,该文件既是给自己用的,也有可能会被其他人使用,因而代码的可读性与易维护性显得十分重要,为此我们在编写一个模块时最好按照统一的规范去编写
------------恢复内容结束------------