Python专家编程系列: 12.Python包(package)中__init__.py的作用

0. 标题

Python专家编程系列: 12.Python包(package)中__init__.py的作用

id: 101

作者: quantgalaxy@outlook.com   
欢迎交流   

1. 什么是包(package)中的 __init__.py 文件

假设你有一个Python目录,里面有一堆Python文件,你想把它当作一个包来对待。只要在里面放一个 __init__.py 文件就行了。
Python会将该目录识别为一个包。这就像代码和Python之间的秘密握手。

__init__.py 文件可以是一个空文件。
如果你需要有些特殊的处理,也可以在里面写上一些代码。
当其他人想要使用你的包时,他们将它导入到他们的代码中,Python首先会去寻找那个神奇的 __init__.py,把它加载起来。

如果没有__init__.py, Python将无法将目录识别为包,并且您将无法使用标准的" import "语句从其中导入模块。

在旧版本的Python(3.3之前)中,必须在包中创建__init__.py文件,然后才能使用from mypackage import mymodule形式的import语句。
自3.3版和PEP 420实现以来,Python将在许多情况下隐式自动创建“命名空间包”。
这意味着__\init__.py现在通常是可选的,但它仍然有助于构建初始化代码并定义像from mypackage import *这样的语句应该如何工作。

2. __init__.py 是如何帮助创建包的

__init__.py允许您将代码组织成模块化块,使所有内容都具有超级可管理性和可重用性。
把它想象成你包的蓝图——你可以在 __init__.py中定义通用函数、变量,甚至导入其他模块,为你的包的功能建立基础。

举例看下:
让我们创建一个名为my_package的简单包来说明 __init__.py如何在my_package目录中工作。
创建一个名为__init__.py的空文件,并创建另一个名为greetings.py的文件,并编写一个名为say_hello()的函数,该函数打印“Hello, World!”

# greetings.py
def say_hello():
    print("Hello, World!")

现在,可以从my_package目录之外的任何文件导入问候模块并使用say_hello()函数。这将打印“Hello, World!”。
因为 __init__.py 使 greetings 模块可以从 my_package 命名空间中访问。

from my_package import greetings
greetings.say_hello()

# Hello, World!

更大和更复杂的包通常使用__init__.py来更好地组织代码,并运行在导入包时应该自动运行的任何初始化。
例如,您可以在 xx/__init__.py文件中添加print行(“Hi from __init__.py”)。现在,如果你导入包,它会立即运行print语句。

3. __init__.py 对 __all__ 的影响

__init__.py中定义的一个常见的东西是 __all__变量。
当用户在程序中运行导入语句时,将覆盖当用户以 “from mypackage import *”" 的形式运行import语句时应该导入的模块和函数。
默认情况下,Python不会从包中导入模块。因此,如果我们更改calculator.py文件中的第一行,从操作中导入所有内容,它将无法工作。

假设我们有一个operations包。
目录布局如下:

├── calculator.py
└── operations
    ├── divider.py
    └── multiplier.py

文件里面的实现如下:
divider.py

# operations/divider.py

class Divider:

    def divide(self, a, b):
        return a / b

multiplier.py

# operations/multiplier.py

class Multiplier:

    def multiply(self, a, b):
        return a * b

calculator.py

# calculator.py

# broken import unless we explicitly define `__all__` in `__init__.py`
from operations import *

mymultiplier = multiplier.Multiplier()
result = mymultiplier.multiply(2, 5)
print(f"2 x 5 is {result}")

mydivider = divider.Divider()
result = mydivider.divide(10, 2)
print(f"10 / 2 is {result}")

如果运行 calculator.py 文件,会触发一个错误:

Traceback (most recent call last):
  File "/Users/g/python_init_example/calculator.py", line 3, in <module>
    mymultiplier = multiplier.Multiplier()
                   ^^^^^^^^^^
NameError: name 'multiplier' is not defined

如果我们在 operations/init.py 中 添加一行:

__all__ = ['divider', 'multiplier']

上面的脚本就可以正常执行了:

2 x 5 is 10
10 / 2 is 5.0

__init__.py是创建结构化和有组织的Python包的基本构建块。
它就像一种无形的粘合剂,将您的代码粘合在一起,使其更容易管理重用和共享。
因此,简单来说,__init__.py就像是Python项目的起跑线。

4. 作者信息

作者: quantgalaxy@outlook.com   
欢迎交流   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

rockwood573

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值