127-豆豆学Python第三集
刘小泽写于19.6.22 函数是程序中可重用的那个部分,而模块就是一个可重用的程序
关于模块
模块(Modules)的目的就是在其他函数中重新使用一些函数,它可以被其他的程序导入然后运行
首先了解标准库模块
# 结果保存为test.py
import sys
print('The commands are:')
for i in sys.argv:
print(i)
print('\n\nThe PATH is:',sys.path,'\n')
以上代码的意思是:
通过
import
导入sys
模块,这个模块就是包含了内置的一些python解释器和环境相关的功能,可以理解为系统功能(system)。运行这个命令,python就会寻找这个模块,内置模块会最先被找到另外注意到存在
sys.argv
和sys.path
,点号左边是模块名,右边是模块中的变量名,其实这样的写法和R很相似,可以避免同一个变量名在多个模块中同时存在时发生冲突sys.argv
返回一系列命令行参数的列表,并且这个列表是以0为第一位索引的,例如,我们输入python test.py i am robot
,结果会返回4个元素:test.py
、i
、am
、robot
,可以看到它也会将程序名作为返回结果,并且作为第一个元素。注意:Python是从0开始计数的sys.path
返回的是一系列目录名称,相当于环境变量,如果模块不在当前返回的环境中,那么就需要将模块先放进去,然后才能加载
和R一样,当前目录是指程序启动的目录。可以利用
import os; print(os.getcwd())
查看每次都写命令的全称(如
sys.path
)还是比较麻烦的,其实可以直接将模块导入(就像R中先将R包加载进来),利用from sys import argv
。虽然这种办法可行,但还是为了避免后续发生名称的冲突,依然推荐使用import
方式
编写自己的模块
每一个脚本都是一个module,只需要将后缀名设为.py
,例如定义一个hi函数,将他保存为myscp.py
:
def hi():
print('Hi, mymodule.')
__version__='0.1'
下面使用这个新建的模块,重新新建一个脚本:
# 导入我们之前建立的python脚本前缀,代表着模块名
import myscp
myscp.hi()
print('Version', myscp.__version__)
# Hi, mymodule.
# Version 0.1
结果返回的就是myscp.py
的模块hi
和__version__
__name__
是什么意思?
看到上面的代码有一个__version__
,它的意思是一个内置变量,统称为__name__
。例如:新建一个文件new_module.py
print('hello')
def main():
print('nihao')
if __name__ == '__main__':
main()
print('Imported from another module')
好,接下来两种运行方式,注意看区别:
# 第一种:直接运行
python new_module.py
# 结果:
hello
nihao
Imported from another module
# 第二种:导入模块
>>> import new_module
# 结果:
hello
可以看到,直接运行是可以全部输出的,但是导入的方式只输出最开始的一行内容。这是因为:每个python脚本(也就是python模块)都包含了内置的变量__name__
,如果是直接运行的话,__name__
相当于文件名(包括了后缀);如果是导入的话,__name__
相当于导入的模块名(不包含后缀)
而__main__
就是直接运行时模块的名称(就是脚本全称)
可以利用这个特性来让模块用不同的方式运行,因此上面代码的意思可以理解为: 当模块直接运行时,def后的代码会直接运行;模块是导入的话,def后的代码不会运行
dir函数
它能够返回对象包含的属性名称,当dir()
有参数且参数是模块名称时,函数返回指定模块对应的名称列表;如果没有指定参数,则返回当前模块的名称列表
import sys
dir(sys)
dir()
# 这两种返回的名称是不相同的
# 如果这时新建一个变量a
a=5
dir()#结果会比之前多了一个a
# 将a再删除后
del a
dir()#又会发生变化
关于包
python的程序是有层次结构的:变量常位于函数内部,函数和全局变量常位于模块内部,而包就是一个包含模块和一个特殊的__int__.py
文件的文件夹,这个文件夹目的就是向python表明:我是特殊的,其中包含了python的模块
例如:我们创建一个world
的包,然后下面可以有asia
、africa
的子包,然后这两个子包中分别存在china
、south_africa
的模块,它的布局就会是这样:
- <某个在sys.path中的路径>
- world/
- __init__.py
- asia/
- __init__.py
- china/
- __init__.py
- test.py
- africa/
- __init__.py
- south_africa/
- __init__.py
- foo.py
因此,包是一种能方便组织模块的管理方式