这里的其他答案可能仍然有点模糊,所以我发布了一个希望更清晰的答案。需要注意的是,问题的标题首先也有点误导,我认为更好的标题是:"与常规模块相比,包模块有什么特别之处?强>".
TL;DR - 简答:
包也是模块,但是它们是它们的一种特殊类型。特殊的意义在于 1. 它们是“目录”,而 2. 它们可能包含特殊文件,例如 __init__.py 和 __main__.py。
为了更好地理解 - 更长的答案:
重点是,包是一种特殊类型的模块,所以我们需要先了解模块的一般性,然后包模块的特殊之处才有意义也。 (注意:我有时会在这个答案中将“包模块”称为“包”,反之亦然)
所以让我们先从总体上谈一谈模块,因为它不那么模糊/更容易理解。 我们对模块主要做两件事,要么将它们导入其他模块,要么直接通过 Python 执行它们。
导入一个模块有一个明确的目标,即访问该模块内部的内容。
然而,执行一个模块通常会追求以下两个目标之一:
- 该模块是一个主模块,执行它会启动我们的程序(或其子程序之一)。
- 我们希望单独尝试该模块的功能,即无需先导入它。
让我们通过一些例子来更清楚地理解所有这些:
导入模块:
# bar.py
def talk():
print("bar")
# foo.py
import bar # <-- importing module "bar"
bar.talk() # <-- prints "bar"
执行模块
目标一,执行一个模块作为主模块:
假设上面示例中的foo.py 模块是启动我们程序的主模块。我们可以在终端输入这个命令来运行它:python3 foo.py # <-- executing a main module,然后它就会启动我们的程序。
目标 2,单独尝试模块的功能:
假设我们想在上面示例中的bar.py 模块中尝试函数talk,而不运行我们的整个程序,即不调用模块foo.py。为此,我们必须稍微更改bar.py:
# bar.py
def talk():
print("bar")
if __name__ == '__main__':
talk()
现在在终端中运行这个命令:python3 bar.py # <-- trying functionalities of a module in isolation,然后它会打印出bar。
现在我们知道了我们可以用模块做什么,让我们回到主要问题:
包模块与常规模块相比有什么特别之处?
1。 Python 中的常规模块只是“文件”,而包模块则是“目录”。
2。常规模块可以“导入”并且可以“执行”(如上面的示例所示),包模块也可以“导入”并且可以“执行”,但是,您可能会抱怨:“但是我们不能直接在目录中写代码!代码只写在文件中!”,这确实是一个很好的抱怨,因为它把我们引向了关于包模块的第二个特别之处。包模块的代码写在其目录下的文件中,这些文件的名称也由 Python 保留。如果你想“导入”一个包模块,你必须把它的代码放在它目录下的__init__.py文件中,如果你想“执行”一个包模块,你必须把执行代码在其目录中的__main__.py 文件中。
这是上面解释的最后一个例子:
# hierarchy of files and folders:
.
├── bar_pack/
│ ├── __init__.py
│ ├── __main__.py
│ foo.py
# bar_pack/__init__.py
def talk():
print("bar")
# bar_pack/__main__.py
import __init__
__init__.talk()
# foo.py
import bar_pack # <-- importing package module "bar_pack"
bar_pack.talk() # <-- prints "bar"
# Run this command in the terminal:
python3 bar_pack # <-- executing the package module "bar_pack", prints "bar"