python学习 - 模块与包的基础概念
文章首发于我的个人博客:欢迎大佬们前来逛逛
@
模块
python提供了一种方法,可以使得在文件编写函数的定义,然后再另一个文件中可以导入这个文件中的函数的定义继而使用。这种文件就叫做模块。
模块可以导入另一个模块或者主模块中。
例如我们创建一个文件,内含两个函数,分别以不同的方式实现斐波那契数列:命名为 fibo.py
''' 斐波那契数列 '''
def fibo(n):
a,b=0,1
while a<n:
print(a,end=' ')
a,b=b,a+b
print()
def get_fibo(n):
l=[]
a,b=0,1
while a<n:
l.append(a)
a,b=b,a+b
return l
然后我们在另一个主文件或者其他文件中导入这个模块
import fibo
然后我们就可以使用fibo模块中的函数了,但是此时我们只是引入模块名 fibo
并没有引入函数名,可以通过模块名来访问函数:
- 通过
模块名+.
来访问 - 可以取一个别名,然后调用别名
# 通过模块访问模块中的函数
fibo.fibo(500)
# 也可以改名
f = fibo.get_fibo
l = f(500)
print(l)
-----------
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
调用模块的不同方式
除了上面的 import 直接导入模块,我们还可以使用下面的方式来导入模块:
from fibo import fibo,get_fibo
:指定导入模块中的fibo和get_fibo的两个函数from fibo import *
:导入fibo中的所有函数。
作为脚本执行模块
在终端中作为脚本来执行此模块,这通常用于测试模块的功能。
只需要在终端中输入如下内容:
>>> python fibo.py <argument>
但是仅仅把我们的刚才的 [fibo.py](http://fibo.py)
文件作为测试是没有效果的,我们需要为 __name__
添加 __main__
属性:即在模块的后面加上如下的代码:
if __name__ == "__main__":
import sys
fibo(int(sys.argv[1]))
这样就可以这个模块像被导入一样来作为脚本执行,此代码只有在模块作为 main
文件执行时才被调用。
>> python fibo.py 50
0 1 1 2 3 5 8 13 21 34
包
包通常是使用用 圆点模块名
的结构化模块命名空间。名为 A.B
的模块表示了名为 A
的包中名为 B
的子模块。
使用包来防止模块之间出现名称相互冲突。
导入包的几种方式:
- 导入包的特定的模块
- 导入包中的子包
- 导入包中的模块的函数
例如我有一个模块,它的路径如下所示:
Include/test_floder/[fibo.py](http://fibo.py/)
其中我们的主文件与Include目录同级,那么我们该如何导导入 [fibo.py](http://fibo.py)
模块呢。
操作形式:from package import item
# ---- 方案一 ------
from Include.test_floder import fibo
fibo.函数名
# ---- 方案二 ------
from Include from test_floder
test_floder.子模块名.函数名
# ---- 方案三 ------
from Include.test_floder.fibo import get_fibo
get_fibo() # 直接使用模块中的函数名
我们也可以直接使用 import
的方式来导入,但是要注意,使用此方法只能导入包或者模块,即上面的方案三无法通过这种方法导入模块内的名字
from Include.test_floder import fibo # 导入了fibo模块
fibo.函数名
从 * 导入包
我们的Include.test_floder
:中有很多的子模块。
如果我们执行了诸如: from Include.test_floder import *
会发生什么?
他会加载这个包中的所有的模块。
很明显这可能会花掉很长时间,并且出现期待之外的边界效应,导出了希望只能显式导入的包。
如果包的作者规定了一个 __init__.py
文件,并且给出了一个名为 __all__
的列表,那么按照列表中给出的模块名进行导入。
例如我们的 Include/test_floder
中是全部的子模块,其中有一个__init__.py
文件,内容如下:
__all__=["fibo", "test1", "test2", "test3"]
那么当我们使用 from Include.test_floder import *
的时候,就会导入该目录中的所有的定义的四个模块
如果我们把 __all__
的内容去掉,则我们在执行 from Include.test_floder import *
时,会发现:我们一个模块都没有导入!!! 因为我们的 * 只会导入 all
中定义的模块。
尽管某些模块设计为使用 import *
时它只导出符合某种规范/模式的命名,仍然不建议在生产代码中使用这种写法。
推荐使用 from Package import specific_submodule
这类写法。
本文来自博客园,作者:hugeYlh,转载请注明原文链接:https://www.cnblogs.com/helloylh/p/17333997.html