对于很多刚入门Python的人来说不太清楚Module和Package的区别。它们都是用来组织代码的,为什么要分两个名字呢?先给一个核心结论,Python模块是单个文件,而包是一个可能包含多个文件的文件夹。比如我们新建一个名为hello.py的文件,里面有两个简单的函数,这就是一个完整的模块:def hello(): return "Hello"def hello_there(): return "Hello, there!"
正如上面的内容,一个模块里可以包含多个成员例如函数、类、变量,只要是写在这个.py文件里的,都属于这个模块。使用起来很简单,把这个hello.py文件放到你当前的工作目录,直接导入就能用:>>> import hello>>> hello.hello()'Hello'>>> hello.hello_there()'Hello, there!'
而package,本质上是一个文件夹,但这个文件夹里可以放多个模块,甚至还能放子包。最基础的包结构,简单到只有一个文件夹+一个特殊文件这个名字为hello的文件夹,里面放了一个__init__.py文件,这就构成了一个python包。那么什么时候用模块,什么时候用包呢?如果代码很简单,只有简单的十几个函数功能单一,不需要拆分,那一个模块.py就足够了,但是入股哦代码比较复杂,比如函数、类的数量变动,功能可以拆分成不同的类别,或者想拆分出子功能,那这时就该用包了。包的核心作用是组织模块,但是如何组织,取决于想给使用的人提供什么样的使用方式,让我们看两个常用的方式。首先以hello包为例,拆分出两个子模块,结构如下:hello/├── __init__.py├── formal.py # 正式问候相关的函数└── informal.py # 非正式问候相关的函数
# formal.pydef greet(): return "Greetings!"
# informal.pydef hey(): return "Hey, there!"
接下来,就看我们想怎么让使用者导入这些函数了。
如果想让使用者明确知道「函数来自哪个子模块」,保持代码的严谨性,那直接让 __init__.py 文件为空就行(甚至可以直接删除 __init__.py 文件,Python 3.3+ 支持这种「命名空间包」,用法和空的 __init__.py 差不多)。这种情况下,使用者需要这样导入和使用:
>>> import hello.informal>>> import hello.formal>>> hello.informal.hey()'Hey, there!'>>> hello.formal.greet()'Greetings!'}
注意:这种方式下,只写 import hello 是无法导入 informal 和 formal 这两个子模块的,必须明确写出子模块的名字,才能访问里面的函数。
大多数时候,我们更希望使用者用起来「更方便」——不用记那么多子模块的名字,导入一次包,就能直接使用里面的核心函数。这时候,__init__.py 文件就派上大用场了!我们在__init__.py 里写这样两行代码:
from .formal import greetfrom .informal import hey
这里的 . 代表「当前包」(也就是 hello 文件夹),意思是「从当前包的 formal 模块导入 greet 函数,从 informal 模块导入 hey 函数」。
>>> import hello>>> hello.hey()'Hey, there!'>>> hello.greet()'Greetings!'}
当然,原来的 hello.informal.hey() 和 hello.formal.greet() 依然可以用,可以根据需求,决定是否鼓励用哪种方式。
最后,希望这篇文章,能帮大家分清 Module 和 Package,以后写 Python 代码,既能保证整洁性,也能提高可维护性~