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 并没有引入函数名,可以通过模块名来访问函数:

  1. 通过 模块名+. 来访问
  2. 可以取一个别名,然后调用别名
# 通过模块访问模块中的函数
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 的子模块。

使用包来防止模块之间出现名称相互冲突。

导入包的几种方式:

  1. 导入包的特定的模块
  2. 导入包中的子包
  3. 导入包中的模块的函数

例如我有一个模块,它的路径如下所示:

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 这类写法。


posted @ 2023-04-19 17:15  hugeYlh  阅读(19)  评论(0编辑  收藏  举报