一 模块
1 ; 什么是模块?
常见的场景:一个模块就是包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀.但其实import加载的模块分为四个通用的类别:
1,使用python编写的代码(.py文件)
2,已被编译为共享库或DLL的C或C++扩展
3,包好一组模块的包
4,使用C编写并链接到python解释器的内置模块
2 为什么要使用模块?
如果你退出python解释器后重新进入,那么你之前定义的函数或者变量都将丢失;因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script.
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的解构更清晰,方便管理.这时我们不仅仅可以把这些文件当脚本去执行,还可以把他们当做模块来导入到其他模块当中,实现了功能的重复利用.
3,如何使用模块?
3.1 import
示例文件: 自定义模块my_module.py , 文件名my_module.py,模块名my_module
#my_module.py print('from the my_module.py') money = 1000 def read1(): print('my_moudle->read1->money',money) def read2(): print('my_module->read2 calling read1') read1() def change(): global money money = 0
3.1.1
模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,他们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中任意位置使用的,且针对同一个模块import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存中.后续的import语句仅是对已加载大内存中的模块对象增加一次引用,不会重新执行模块内的语句))

#demo.py import my_module #只在第一次导入时才被执行my_module.py内代码,此处的显示效果只打印一次'from the my_module.py',当然其他的顶级代码也都被执行了,只不过没有显示效果. import my_module import my_module import my_module ''' 执行结果: from the my_module.py '''
3.1.2
被导入的模块有独立的名称空间
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突;

#test.py import spam money = 10 print(spam.money) ''' 执行结果: form the spam.py 1000 '''

#test.py import spam import spam def reada(): print('=====') spam.read1() ''' 执行结果: form the spam.py spam->read1->money 1000 '''

#test.py import spam money = 1 spam.change() print(money) ''' 执行结果: from the spam.py 1 '''
3.1.3
为模块名起别名 as语句
为已经导入的模块起别名的方式对编写可扩展的代码很有用
import spam as sm print(sm.money)
3.1.4
在一行导入多个模块
import sys,os,re
3.2 使用模块之 from...import...
3.2.1
from...import...的使用
from spam import read1,read2
3.2.2
from...import与import的对比
#唯一的区别就是:使用from...import...则是将spam中的名字直接导入到当前的名称空间中,所以在当前名称空间中使用名字就可以了,无需加前缀:spam. #from...import...的方式有好处也有缺点 好处:使用起来方便 坏处:容易与当前执行文件中的名字冲突
当前位置直接使用read1和read2就好了,执行时,仍然以spam.py文件全局名称空间

#测试一:导入的函数read1,执行时仍然回到spam.py中寻找全局变量money #test.py from spam import read1 money = 1000 read1() ''' 执行结果: from the spam.py spam->read1->money 1000 ''' #测试二:导入的函数read2,执行时需要调用read1(),仍然回到spam.py中找read1() #test.py from spam import read2 def read1(): print('======') read2() ''' 执行结果: from the spam.py spam->read2 calling read spam->read1->money 1000 '''
如果当前有重名read1或者read2,那么会产生覆盖效果
导入的方法在执行时,始终是以源文件为准
4.支持as
from spam import read1 as read
5.一行导入多个名字
from spam import read1,read2,money
6.from...import*
#from spam import* *把spam中所有的不是以下划线(_)开头的名字都导入到当前位置 #大部分情况下我们的python程序不应该使用这种导入方式,因为*你不知道导入什么名字,很有可能覆盖掉你之前已经定义的名字.而且可读性极差,在交互环境中导入时没有问题.
可以使用__all__来控制*(用来发布新版本),在spam.py中新增一行
__all__ = ['money','read1'] #这样在另外一个文件中使用from spam import* 就这样导入列表中规定的两个名字
7.模块引用中的情况:
1,模块的循环引用
模块之间不允许循环引用
2.模块的加载与修改
已经被导入的模块发生了修改,是不会被感知到的
要想修改的模块被正在运行中的程序感知到,重启这个程序
3.把模块当成脚本执行
if __name__ == '__main__':
代码
写在这里的代码只有这个文件被当做脚本执行的时候才被执行
4.模块的搜索路径
和被当做脚本执行的文件 同目录下的模块,可以被直接导入
除此之外其他路径下的模块在被导入需要自己修改sys.path列表