1.7 标准库与扩展库中对象的导入与使用
Python默认安装仅包含基本或核心模块,启动时也仅加载了基本模块,在需要时再显式地导入和加载标准库和第三方扩展库,这样可以减小程序运行的压力,并且具有很强的可扩展性。从“木桶原理”的角度来看,这样的设计与安全配置时遵循的“最小权限”原则是一致的,也有助于提高系统安全性。如果需要的话,可以使用sys.modules.items()显示所有预加载模块的相关信息。另外,可以使用sys.builtin_module_names查看那些编译进Python解释器的模块名字,这些模块具有最快的访问速度和最高的执行效率。
当以模块形式导入.py或.pyw源文件时,系统会自动检查__pycache__文件夹中是否存在相应的.pyc文件,如果有且签名一致则自动从.pyc文件导入以提高加载速度,如果源文件具有比.pyc文件更新的签名,那么导入时会自动重新生成.pyc文件。但需注意的是,如果源文件不存在,导入时不会检查__pycache__文件夹。因此,如果想实现无源码部署,应该把所有.pyc文件放到源文件的文件夹中而不是__pycache__文件夹中。
1.7.1 import模块名 [as别名]
使用这种方式导入以后,使用时需要在对象之前加上模块名作为前缀,必须以“模块名.对象名”的形式进行访问。如果模块名字很长的话,可以为导入的模块设置一个别名,然后使用“别名.对象名”的方式来使用其中的对象。
>>>import math #导入标准库math >>>math.sin(0.5) #求0.5(单位是弧度)的正弦 0.479425538604203 >>>import random #导入标准库random >>>n=random.random() #获得[0,1)内的随机小数 >>>n=random.randint(1,100) #获得[1,100]区间上的随机整数 >>>n=random.randrange(1,100) #返回[1,100)区间中的随机整数 >>>import os.path as path #导入标准库os.path,并设置别名为path >>>path.isfile(r'C:\windows\notepad.exe') True >>>import numpy as np #导入扩展库numpy,并设置别名为np >>>a=np.array((1,2,3,4)) #通过模块的别名来访问其中的对象 >>>a array([1,2,3,4]) >>>print(a) [1 2 3 4]
1.7.2 from模块名import对象名[as别名]
使用这种方式仅导入明确指定的对象,并且可以为导入的对象确定一个别名。这种导入方式可以减少查询次数,提高访问速度,同时也可以减少程序员需要输入的代码量,不需要使用模块名作为前缀。
>>>from math import sin #只导入模块中的指定对象 >>>sin(3) 0.1411200080598672 >>>from math import sin as f #给导入的对象起个别名 >>>f(3) 0.1411200080598672 >>>from os.path import isfile >>>isfile(r'C:\windows\notepad.exe') True
1.7.3 from模块名import*
这是上面用法的一种极端情况,可以一次导入模块中通过__all__变量指定的所有对象。
>>>from math import* #导入标准库math中所有对象 >>>gcd(36,18) #最大公约数 18 >>>pi #常数π 3.141592653589793 >>>e #常数e 2.718281828459045 >>>log2(8) #计算以2为底的对数值 3.0 >>>log10(100) #计算以10为底的对数值 2.0 >>>radians(180) #把角度转换为弧度 3.141592653589793
这种方式简单粗暴,写起来也比较省事,可以直接使用模块中的所有对象而不需要再使用模块名作为前缀。但一般并不推荐这样使用。一方面这样会降低代码的可读性,有时候很难区分自定义函数和从模块中导入的函数;另一方面,这种导入对象的方式将会导致命名空间的混乱。如果多个模块中有同名的对象,只有最后一个导入的模块中的对象是有效的,而之前导入的模块中的同名对象都将无法访问,不利于代码的理解和维护。例如,a.py文件中内容如下:
def test(): print('test in a.py')
b.py文件中内容如下:
def test(): print('test in b.py')
导入a模块以后,test()方法是可用的,而导入b模块之后a模块中的test()方法就无法使用了。例如:
>>>from a import* >>>test() test in a.py >>>from b import* #这会导致a模块中的test()函数无法使用 >>>test() test in b.py
1.7.4 模块导入时的搜索路径
不管以哪种形式导入模块并使用其中的对象,Python首先在当前目录中查找模块文件,如果没有找到则从sys模块的path变量所指定的目录中查找,如果仍没有找到则抛出异常提示模块不存在。可以查看sys模块中path变量的值来获知Python导入模块时搜索模块的路径,也可以使用append()方法向其中添加自定义的文件夹以扩展搜索路径。另外,在导入模块时,会优先导入相应的.pyc文件(.py或.pyw伪编译后生成的字节码文件),如果相应的.pyc文件与.py文件时间不相符或不存在对应的.pyc文件,则导入.py文件,同时生成.pyc文件。
Python还支持从zip文件中导入模块。假设当前文件夹中有个内含Vector3.py文件的testZip.zip文件,首先导入sys模块,然后执行sys.path.append('testZip.zip'),然后即可导入Vector3.py文件作为模块来使用。
>>>import sys >>>sys.path.append('testZip.zip') >>>import Vector3 >>>Vector3.__file__ #查看已导入模块对应的程序文件 'testZip.zip\\Vector3.py'
最后,按照Python编码规范,一般建议每个import语句只导入一个模块,并且要按照标准库、扩展库、自定义库的顺序进行导入。