python __init__.py 的學(xué)習(xí)(轉(zhuǎn))

Python雜談: init.py的作用

我們經(jīng)常在python的模塊目錄中會(huì)看到 "init.py" 這個(gè)文件,那么它到底有什么作用呢?

1. 標(biāo)識(shí)該目錄是一個(gè)python的模塊包(module package)

如果你是使用python的相關(guān)IDE來(lái)進(jìn)行開(kāi)發(fā),那么如果目錄中存在該文件,該目錄就會(huì)被識(shí)別為 module package 。

2. 簡(jiǎn)化模塊導(dǎo)入操作

假設(shè)我們的模塊包的目錄結(jié)構(gòu)如下:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">.
└── mypackage
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

如果我們使用最直接的導(dǎo)入方式,將整個(gè)文件拷貝到工程目錄下,然后直接導(dǎo)入:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from mypackage.subpackage_1 import test11 from mypackage.subpackage_1 import test12 from mypackage.subpackage_2 import test21 from mypackage.subpackage_2 import test22 from mypackage.subpackage_3 import test31 from mypackage.subpackage_3 import test32</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

當(dāng)然這個(gè)例子里面文件比較少,如果模塊比較大,目錄比較深的話,可能自己都記不清該如何導(dǎo)入。(很有可能,哪怕只想導(dǎo)入一個(gè)模塊都要在目錄中找很久)

這種情況下,init.py 就很有作用了。我們先來(lái)看看該文件是如何工作的。

2.1 init.py 是怎么工作的?

實(shí)際上,如果目錄中包含了 init.py 時(shí),當(dāng)用 import 導(dǎo)入該目錄時(shí),會(huì)執(zhí)行 init.py 里面的代碼。

我們?cè)趍ypackage目錄下增加一個(gè) init.py 文件來(lái)做一個(gè)實(shí)驗(yàn):

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">.
└── mypackage
├── init.py
├── subpackage_1
│ ├── test11.py
│ └── test12.py
├── subpackage_2
│ ├── test21.py
│ └── test22.py
└── subpackage_3
├── test31.py
└── test32.py</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

mypackage/init.py 里面加一個(gè)print,如果執(zhí)行了該文件就會(huì)輸出:

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">print("You have imported mypackage")</pre>

下面直接用交互模式進(jìn)行 import

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">>>> import mypackage
You have imported mypackage</pre>

很顯然,init.py 在包被導(dǎo)入時(shí)會(huì)被執(zhí)行。

2.2 控制模塊導(dǎo)入

我們?cè)僮鲆粋€(gè)實(shí)驗(yàn),在 mypackage/init.py 添加以下語(yǔ)句:

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from subpackage_1 import test11</pre>

我們導(dǎo)入 mypackage 試試:

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">>>> import mypackage
Traceback (most recent call last):
File "<stdin>", line 1, in <module> File "/home/taopeng/Workspace/Test/mypackage/init.py", line 2, in <module>
from subpackage_1 import test11
ImportError: No module named 'subpackage_1'</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

報(bào)錯(cuò)了。。。怎么回事?

原來(lái),在我們執(zhí)行import時(shí),當(dāng)前目錄是不會(huì)變的(就算是執(zhí)行子目錄的文件),還是需要完整的包名。

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from mypackage.subpackage_1 import test11</pre>

綜上,我們可以在init.py 指定默認(rèn)需要導(dǎo)入的模塊

2.3 偷懶的導(dǎo)入方法

有時(shí)候我們?cè)谧鰧?dǎo)入時(shí)會(huì)偷懶,將包中的所有內(nèi)容導(dǎo)入

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from mypackage import *</pre>

這是怎么實(shí)現(xiàn)的呢? **all **變量就是干這個(gè)工作的。

all 關(guān)聯(lián)了一個(gè)模塊列表,當(dāng)執(zhí)行** from xx import * **時(shí),就會(huì)導(dǎo)入列表中的模塊。我們將 init.py 修改為 。

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">all = ['subpackage_1', 'subpackage_2']</pre>

這里沒(méi)有包含 subpackage_3,是為了證明 **all **起作用了,而不是導(dǎo)入了所有子目錄。

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">>>> from mypackage import *

dir()
['builtins', 'doc', 'loader', 'name', 'package', 'spec', 'subpackage_1', 'subpackage_2'] >>>
dir(subpackage_1)
['doc', 'loader', 'name', 'package', 'path', 'spec']</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

子目錄的中的模塊沒(méi)有導(dǎo)入?。。?/strong>

該例子中的導(dǎo)入等價(jià)于

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">from mypackage import subpackage_1, subpackage_2</pre>

因此,導(dǎo)入操作會(huì)繼續(xù)查找 subpackage_1 和 subpackage_2 中的 init.py 并執(zhí)行。(但是此時(shí)不會(huì)執(zhí)行** import ***)

我們?cè)?subpackage_1 下添加 init.py 文件:

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">all = ['test11', 'test12'] # 默認(rèn)只導(dǎo)入test11
from mypackage.subpackage_1 import test11</pre>

再來(lái)導(dǎo)入試試

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">>>> from mypackage import *

dir()
['builtins', 'doc', 'loader', 'name', 'package', 'spec', 'subpackage_1', 'subpackage_2'] >>>
dir(subpackage_1)
['all', 'builtins', 'cached', 'doc', 'file', 'loader', 'name', 'package', 'path', 'spec', 'test11']</pre>

[
復(fù)制代碼

](javascript:void(0); "復(fù)制代碼")

如果想要導(dǎo)入子包的所有模塊,則需要更精確指定。

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px !important;">>>> from mypackage.subpackage_1 import *

dir()
['builtins', 'doc', 'loader', 'name', 'package', 'spec', 'test11', 'test12']</pre>

3. 配置模塊的初始化操作

在了解了 init.py 的工作原理后,應(yīng)該能理解該文件就是一個(gè)正常的python代碼文件。

因此可以將初始化代碼放入該文件中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容