创建包(定义)

在python工程下的文件夹,如果它直接包含了__init__.py,那它就会被认为是一个 python包
无论对于多少级的子文件夹,这一条都生效

管理包(init.py的用法)

既然是一个包,那它里面就会包含多个文件,以及大量的函数、类、实例等,那么哪些需要对外透明,哪些不需要被外部知晓,就成了一个必须考虑的问题,
每次在工程入口直接import包内部具体的文件并不是一个明智的选择,这会导致import臃肿且无法明确管理包内部的行为,这种import仅仅是将“包”作为一个文件夹,而不是一个python意义上的“包”,
顺理成章的,就需要一个东西来优化上面的问题,这就是__init__.py,它有三大功能

  • 声明当前目录是一个 Python 包
  • 可以控制对外暴露的 API(即 from package import * 时能导入哪些)
  • 可以做一些包的初始化逻辑(如日志配置、版本号声明等)

常见的用法

以下面的工程树举例

.
├── entry.py
└── pkgs
    ├── Node0
    │   └── arm.py
    └── Node1
        └── head.py

首先,为每个你认为是包的子文件夹添加__init__.py,比如这样

.
├── entry.py
└── pkgs
    ├── __init__.py
    ├── Node0
    │   ├── arm.py
    │   └── __init__.py
    └── Node1
        ├── __init__.py
        └── head.py

然后我们假设arm.py包含一个class arm_controller, head.py包含一个class head_controller

# arm.py
print("arm has been imported!")
class arm_controller(object):
    def __init__(self):
        pass

# head.py
print("head has been imported!")
class head_controller(object):
    def __init__(self):
        pass

常见且比较规范的做法是:

# pkgs/__init__.py
from .Node0 import arm
from .Node1 import head
__all__ = ["arm", "head"]

# pkgs/Node0/__init__.py
from . import arm
__all__ = ["arm"]

# pkgs/Node1/__init__.py
from . import head
__all__ = ["head"]

如此可以实现:

  1. 在顶层包 pkgs 就能访问核心模块 face 和 neck
  2. 子包 Node0 和 Node1 内部仍然是清晰独立的
  3. __all__ 明确了包的公共 API,符合“最小可见性原则”,即上层程序想直接from … import *时,只会导入pkg希望被import的部分,而不是一次性被全部import
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐