Package Management
为了实现软件功能的复用,在Python中定义了包、模块、类、函数等组件。若干函数和类组成了模块,若干模块及子包组成了包。包的概念在各主流语言中都有,项目一旦到达一定的规模就必定会需要包类似的结构进行功能重组、复用。这里对Python中包的使用进行简单总结,并类比其他几种语言中的包管理机制。
Python 函数
Python 类
Python 模块
- Python 支持面向过程式编程和面向对象式编程(以及一定程度上函数式编程),函数和类组成了包中的基本单位模块(如果愿意也可以定义一些全局变量)
__all__
变量定义 from my_module import *
调用时导入的元素,如果不定义 __all__
变量则默认导入所有元素
Python 包
- 在文件夹中定义
__init__.py
文件,文件内容可以为空 __all__
变量定义 from my_package import *
调用时导入的元素,如果不定义__all__
变量则默认不导入任何元素 - 直接
import my_package
导入的是包中的 __init__.py
,如果 __init__.py
中没有对任何子元素的导入操作则import my_package
没有意义
其他语言包机制
java
- java 中的包也是由文件夹划分的
- 在源文件中必须明确指示包名
package xxx.xxx.xxx
,但文件夹中无需定义 __init__.py
类似的声明文件 - java 的文件名设置也是由限制的,一个文件最多一个公共类,文件名需要与此公共类相同
SCALA
- scala 的包定义机制与 java 类似,但比 java 更加灵活,可以在源文件中直接定义嵌套包
- scala 的文件名设置没有 java 这种限制
- 为了直接定义一些全局工具函数,scala 提供了包对象
C#
- C# 使用命名空间和程序集包实现功能复用,实现类似包的机制
- 命名空间和程序集没有一对一的关系,一个命名空间可以属于多个程序集,一个程序集也可以包含多个命名空间
- 使用程序集中的元素时,需要先添加该程序集的引用,然后在导入其命名空间(或者不嫌麻烦也可以直接使用全限定名),才能使用
GO
- GO 也是用包对软件功能模块进行管理的,但 GO 也无需定义
__init__.py
类似的声明文件 - GO 的包定义同 java 也是 package 关键字,但是 GO 中的包名与目录的对应关系与 java 不同,简单一句话:java 是包内目录,GO 是包外目录。
- GO 中的包导入需要使用的是包所在相对于 GOPATH 的路径,导入后获得的包名是源文件中定义的包名,一个文件夹中所有源文件必须属于同一个包名,否则会有编译错误
C++
- C++ 使用命名空间和链接库实现包类似机制,与 C# 比较类似,不同的是导入元素时 C++ 需要引用相关头文件,而C#添加程序集引用后直接导入命名空间