Python易学就会(二)import的用法
前文有叙,Python是开放型社群化的开发语言,所以我们在编写Python程序时,不可避免的需要用到别人已经做好的、成型的类库,这些类库可能是图形处理、可能是网络通讯、可能是数据分析等等,反正不需要自己来重新从最底层开始再写一遍,这样就需要用到import 来引入外来的拓展包。
能否找到更多的第三方库、拓展包,也因此成为评判一个编程语言的开发社区是否活跃、是否易用的一个标志。所以,学会用好import就成为我们学习Python需要重点了解的第一个内容。
Python能通过import 引入的,有模块(module)和包(package)两种。
模块(module)的作用,就是可以把一组相关的功能,集成在一个 .py 文件中,方便在其它应用中通过 import 引入来调用。比如跟时间相关的操作,都集成在一个 module 中,使用时这样来操作。
#引入time模块 import time #调用time模块的sleep()方法 time.sleep(1)
不同人写的模块(module)有可能会重名,例如A写了个time.py模块,B也写了个time.py,他们中间各有一个方法非常好用,对于C来说,就容易混淆了。因此有了包(package)的概念。
包(package)是在module的外面加了一层,如
#引入A的time模块 import A.time #引入B的time模块 import B.time #调用A的time模块的sleep()方法 A.time.sleep(1) #调用B的time模块的方法 B.time.setTime(0)
就相当于JAVA中的PACKAGE。物理上体现在:模块(module)可以放在同一目录下,而包(package)一般放在以包名命名的文件夹中。下面以例子来解释。
新建 lmModule.py,内容如下
print("From lmModule.py")
运行一下,可以看到正常打印
From lmModule.py
在同一目录中再新建一个main01.py,内容如下
import lmModule print("From main01.py")
运行一下,可以看到打印出来:
From lmModule.py From main01.py
由此可见,import实际上是把要导入的程序预先加载在了主程序的前部,两者的内容都得到了执行。
修改一下lmModule.py的内容,添加一个变量和一个方法:
print("From lmModule.py") lmModule_var = "LmModule Var" def lmModule_method(): print("From lmModule.py lmModule_method")
再修改一下main01.py,来尝试调用一下模块的变量和方法:
import lmModule print("From main01.py") print(lmModule.lmModule_var) lmModule.lmModule_method()
运行发现,使用“模块名+.”的方式,可以很好的实现调用,运行结果如下:
From lmModule.py From main01.py LmModule Var From lmModule.py lmModule_method
再次修改main01.py,尝试不同的import方法:
from lmModule import lmModule_var, lmModule_method print("From main01.py") print(lmModule_var) lmModule_method()
用“from 模块名 import 部分变量或方法”这种方式,可以从模块中引入特定的的变量或方法,这些变量或方法可以直接使用,就像程序自己定义的一样,再不需要用“模块名+.”来访问。如果需要引入所有的变量或方法,可以改写成通配符*,执行效果一样。
from lmModule import * print("From main01.py") print(lmModule_var) lmModule_method()
接下来,新建一个目录dir,在dir下面新建一个“dirModule.py”,内容如下:
print("From dir dirModule")
修改main01.py,内容如下,以引入dir目录下的dirModule模块:
from lmModule import * from dir.dirModule import * print("From main01.py") print(lmModule_var) lmModule_method()
执行发现,把模块定义在下级目录中,也是可以顺利import到的,执行效果如下
From lmModule.py From dir dirModule From main01.py LmModule Var From lmModule.py lmModule_method
修改dirModule.py,在其中加入一个变量和一个方法的定义,内容如下:
print("From dir dirModule") lmModule_var = "DirModule Var" def lmModule_method(): print("From dir dirModule.py lmModule_method")
执行main01.py,可以看到,当先后import的两个模块中,有相同的变量定义或方法定义时,前面先import的会被后import的覆盖,执行效果如下:
From lmModule.py From dir dirModule From main01.py DirModule Var From dir dirModule.py lmModule_method
如果修改main01.py,交换import的顺序,可以看到,执行的结果不同,先import的会被后import的覆盖,你可以自己试试。
为避免这种相互覆盖而出错的情况,import 时还是尽量使用“模块名+.”的方式来访问,当然可以用别名。修改main01.py如下:
import dir.dirModule as d import lmModule as h print("From main01.py") print(h.lmModule_var) d.lmModule_method()
执行效果如下:
From dir dirModule From lmModule.py From main01.py LmModule Var From dir dirModule.py lmModule_method
在dir目录下新建一个“secModule.py"文件,内容如下:
print("From dir secModule") secModule_var = "SecModule Var"
修改main01.py,增加对于secModule模块的调用,内容如下:
import dir.dirModule as d import dir.secModule import lmModule as h print("From main01.py") print(h.lmModule_var) d.lmModule_method() print(dir.secModule.secModule_var)
执行一下,可以看到secModule模块的内容正常被引入了,secModule模块中定义的变量也可以使用。
From dir dirModule From dir secModule From lmModule.py From main01.py LmModule Var From dir dirModule.py lmModule_method SecModule Var
好,那么如果想一次性导入dir目录下的多个文件,可行吗,经测试 import dir.* 是不好使的;import dir 更是不好使。那怎么办呢?
该包(package)上场了!
在dir目录下新建“__init__.py”,内容如下:
from . import secModule from . import dirModule
有了这个“__init__.py”,就把dir由一个目录,变成了一个包(package)。Python只要在目录下找到这个文件,就会按package来处理,下面我们修改一下main01.py的内容:
import dir import lmModule as h print("From main01.py") print(h.lmModule_var) dir.dirModule.lmModule_method() print(dir.secModule.secModule_var)
执行一下,可见通过import一个包dir,可以将包中的所在module都引入进来。执行效果如下:
From dir secModule From dir dirModule From lmModule.py From main01.py LmModule Var From dir dirModule.py lmModule_method SecModule Var
当然__init__.py中也可以定义变量和方法。而且,如果“__init__.py”中包含了变量“__all__”,那么将只有“__all__”中所指定的变量或方法能被外部访问!“__all__”中所指定的变量或方法相当于JAVA中的public。