一、模块(Module)
- 创建一个
文件夹或者文件。
├── run.py
├── calculate
│ ├── add.py
│ ├── divde.py
│ ├── multi.py
│ └── sub.py
调用模块。
# Filename:add.py
def add( a, b):
return a+ b
# Filename:run.py
from calculate import add
print( add.add( 1,2))
调用模块需要用到 from 关键词,如果直接使用 import 会是什么结果?
import calculate.add
print( dir( add))
""" Output
Traceback (most recent call last):
File "./run.py", line 7, in <module>
print( dir( add))
NameError: name 'add' is not defined
"""
add方法出错了?使用dir()查看,似乎calculate包并没有add方法,这是怎么回事?
没有加 __init__.py 文件!
如果一个包没有__init__.py文件,就会被看成一个普通的文件夹,虽说普通文件夹也能够import,但是并不能实现什么功能。
- 添加空
__init__.py
# filename: run.py
import calculate
print( dir( calculate ))
"""
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
"""
为什么还是提示没有 add 方法?明明已经有 __init__.py文件了?
经查阅资料,
__init__.py控制着包的导入行为,假如__init__.py为空,那么仅仅导入包是什么都做不了的,也不能访问包下面的模块;
只有当在__init__.py将模块逐一import,导入包后才能有效地使用包中的模块。
当然,没有在__init__.py中 import 模块的包,还是可以通过 from 包 import 模块的方式导入模块。
所以在 __init__.py 为空的时候,还是可以通过(也只能通过)以下方法使用各个模块。
# filename: run.py
from calculate import add
print( add.add(1,2) )
要注意:包、模块、方法是三个级别的东西,譬如上面的 calculate 是包,import 导入的是 add 模块,模块 add 中的 add 是函数方法。等级一定要清晰明了,不然会出错。
当然,也可以直接导入模块里面的函数方法,这样使用过程中就不用冗长的前缀了。
一般来说,导入包中所有的模块可以使用 from 包 import *,但是看上面一段代码,似乎并没能导入全部模块之后,而单独导入某一个模块是成功的。这是为什么?最终还是要归结于 __init__.py 的内容。
二、包(Package)
- 给
__init__.py添加内容
将所有的模块名称以列表的形式赋值给__all__属性,就可以导入所有模块。
# filename:__init__.py
# 注意,一定要写包的名称 calculate.作为前缀,不然会找不到模块!
from calculate import (
add,
sub,
multi,
divde
)
__all__ = [ 'add', 'sub', 'multi', 'divde']
# filename: run.py
import calculate
print( dir( calculate ))
"""
['__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'add', 'divde', 'multi', 'sub']
"""
总之,导入时,package 内的 module 是受 __init__.py 限制的。
本文深入探讨了Python中模块(Module)与包(Package)的概念,详细解析了如何创建和调用模块,以及__init__.py文件在包管理中的关键作用。通过实例说明了在不同情况下模块的导入方式和包内模块的访问方法。
3万+

被折叠的 条评论
为什么被折叠?



