模块:
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀(模块名不能定义成中文)
为何要使用模块:
因为退出python解释器然后在进入python解释器,那么你之前定义的函数或者变量都将丢失,因此我们通常都将程序写到文件中便永久保存下来,需要时就通过python *.py方式去运行,此时的*.py被称为脚本script。
站在开发效率来讲,随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这是我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他模块中,实现了功能的重复利用
那么如何使用模块呢?
import
#test.py
print('from the test.py')
money=1000
defread1():print('spam->read1->money',1000)defread2():print('spam->read2 calling read')
read1()defchange():globalmoney
money=0
test.py(module)
import test #导入模块,导入就是在执行导入的文件
#导入模块后,就是通过import定义一个模块名,并且这个模块下的所以名字都因此在test名字的后面
print(test.money) #这样才能取到test模块下面的各种变量
use_test.py(use module)
请看下图
要想取出test下的money变量的值,需要通过test这个'门牌号'来取 就是print(test.money)
如果在当前文件中又定义了一个新的money变量。再次执行print(test.money)的结果还是原来的值。因为即使当前目录下定义了相同的变量,但是它们的内存地址并不一样。不管怎么写,只要是通过模块名去调用模块下面的代码,那么执行的结果一定是原来的东西
导入模块最倡导的方式就是'模块名.调用名'
import test #import只会在第一次导入时才会执行,后面的导入都是在引用之前创建好的名字。不会再把文件内容执行
importtestimporttestimport test #即使导入多次也是执行一次效果#import过程就是要执行文件里面的代码,是文件就要有路径,所以import是一个找文件的过程。为什么能在当前目录下导入直接导入模块,因为调用与被调用模块都在同一个目录下,所以直接就能找到,调用。并且impor导入多次t不能每次都找,那样速度会慢。
我们可以使用sys.module找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入
importtest as teprint(te.money) #为模块起别名 ,适用于那种模块名很长,或者以冲突的模块名#起别名还有一个好处就是扩展性强#比如说两个模块都可以处理相同的问题 那么可以把这两个定义成一个别名,在调用的时候会很方便
if file_format == 'xml':importxmlreader as readerelif file_format == 'csv':importcsvreader as reader
data=reader.read_date('filename')
import os,sys,time,test #一行导入多个模块
from ... import ...
相对于import test来说,它会将源文件的名称空间'test'带入到当前名称空间中,使用时必须是test.名字的方式,而from语句相当于import,也会创建新的名称空间,但是将test中的名字直接导入到当前名称空间中,在当前名称空间中,使用名字可以直接调用
from test import read1,read2 #注意 调用名字标红并不是报错,只是系统不识别自己定义的模块
read1()
read2()
PS:但是如果当前导入的模块里有跟当前名称空间相冲突的名字,那么下面的名字就会覆盖上面
这种方法就是不需要进行test.最为前缀去调用,但是它的执行仍然跟test.执行一样,仍然要回到之前的名称空间中去运行
强烈不建议用from ... import 方法
也可以支持起别名
也支持多行导入
from test import * #导入所有,不推荐#但是在某些情况下还得使用,各自体会吧
如果我在模块中,将一个名字以下划线(_)开头,那么import将无法导入
#但是可以通过用下面方法还是可以执行的
from test import _money
__all__
__all__=['money','read1']#如果使用了__all__参数那么后面要跟一个列表,然后里面以字符串的方式写入,代表着如果里面写入了一些名字,那么谁在通过import test from *调用,只会调用__all__里面的名字,read2将不会调用
将模块当做脚运行
在模块中,最下方输入print(__name__),然后倒入模块后,会执行模块的内容,并且输入模块名,这个模块名就是print(__name__)执行的
但是模块只能被导入么?答案是否定的,模块也能单独当一个脚本执行。如果单独执行那么print(__name__)的输出就是__main__
所以通过__name__可以标识一种状态,文件此刻被已一种什么样的方式去使用。如果是__main__那么就当做脚本去执行,如果是文件名本身那么就是被调用。
通过 if __name__ =='__main__' 来控制文件在不同的场景下有不同执行效果。
模块搜索路径
导入模块:首先会从内存中找內建模块;如果不存在,然后会去系统的环境变量里找;如果不在当前目录,那么需要将要导入模块的路径添加到sys.path中,使用sys.path.append('路径');
在Python中导入代码会在Python中__pycache__目录下产生一个文件如(test.cpython-33.pyc)这个里面的test就是被导入的模块,而这个文件就是为了提高模块的导入速度。
导入包
包:就是一个目录,在Python中,一个文件夹中有__init__.py的文件
无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
包A与包B下有相同的模块也不会冲突,如A.a与B.a这是来自两个命名空间
包结构
glance/ #Top-level package
├──__init__.py #Initialize the glance package
├── api#Subpackage for api
│ ├──__init__.py
│ ├── policy.py
│ └── versions.py
├── cmd#Subpackage for cmd
│ ├──__init__.py
│ └── manage.py
└── db#Subpackage for db
├──__init__.py
└── models.py
文件中代码
#文件内容
#policy.py
defget():print('from policy.py')#versions.py
defcreate_resource(conf):print('from version.py:',conf)#manage.py
defmain():print('from manage.py')#models.py
defregister_models(engine):print('from models.py:',engine)
注意事项
1.关于包相关的导入语句也分为import和from...import...两种,但是无论哪种,无论什么位置,在导入时都必须遵循一个原则:凡事在导入时带点的,点的左边必须是一个包,否则非法。可以带有一连串的点,如item.subitem,subsubitem.但是都必须遵循这个原则
2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数类(他们都可以用点的方式调用自己的属性)
3.对比import item 和from item import name的应用场景:
如果我们想直接使用name,那么必须使用后者
import sys
importglance.api.policy as g1print(sys.path)
g1.get()
from...import...
需要注意的是from...import导入的模块,import后面必须是导一个具体的目标,错误语法(from a import b.c)正确语法(from a.b.c import d)
import后面不需要写点,后面不需要再进行找包的过程,找包的过程都是在from a.b.c 来完成的
from glance.api.policy importget
get()
#或者
from glance.api import policy
policy.get()
导入包时做了什么事?
导入文件的时候,会执行文件,那么导入包呢? 在每个包中都会有一个__init__文件,那么在导入的时候会首先执行init文件,然后会在当前位置产生一个名字,这个名字来引用一个名称空间。
#如果直接导入glance包并且调用glance.api.policy下面的get方法需要怎么做?
importglance
glance.get()
如果如上述方法肯定会报错。因为你已经知道导入包就是执行包下面的__init__文件,那么可以用glacne下__init__文件来导入glance下的包,在通过其他文件来导入glance这个大包。
#在__init__中导入这个policy包,
from glance.