if __name__ == __main___if __name__ == '__main__': 究竟起什麼作用,閱讀本文後,其他文章不必再看...
def func():
print('ok')
if __name__ == '__main__':
func()
這種形式的程式碼,相信你已經見過很多,在指令碼的末尾,出現一個if條件判斷,這個if條件判斷的作用是什麼呢, __name__ 事先並沒有定義,為什麼可以直接使用呢,它從哪裡來? 回答這些問題,必須先了解模組屬性
1、模組屬性
一個python指令碼(以.py 結尾的檔案)就是一個模組,模組自身有若干屬性,其中比較常用的是如下兩個
1. __name__ 模組的名稱
2. __file__ 指令碼的完整檔案路徑
在任意一個python腳本里,你都可以輸出這兩個屬性
print(__name__)
print(__file__)
得到結果
__main__
/Users/zhangdongsheng/experiment/test/test.py
__name__ 的值是 __main__ ,這表示模組的名稱是__main__
__file__ 是檔案的完整路徑
雖然弄清楚了__name__ 是怎麼一回事,但也帶來了新的疑問,明明__name__ 就等於 __main__ ,為何還要做if條件判斷呢?顯然是存在 __name__ 不等於__main__ 的情況。
2、直接執行與其他模組引入
簡單的功能,我們可以在一個python腳本里完成,但複雜的功能,我們會寫多個python 指令碼,比如下面的例子裡,有兩個指令碼,一個是main.py ,做為整個程式的啟動指令碼,utils.py 提供一些輔助函式,供main.py使用
(1)utils.py
def safe_division(a, b):
if b == 0:
return None
return a/b
print("utils 模組裡的__name__ 值為:", __name__)
(2)main.py
from utils import safe_division def func(): value = input("輸入兩個整數,中間用空格分開:") arrs = value.split() a = int(arrs[0]) b = int(arrs[1]) result = safe_division(a, b) print(result) if __name__ == '__main__': func()
接下來,通過兩步實驗,來理解 __name__ 在不同場景下的取值情況。
第一步,先來執行utils.py檔案
python utils.py
執行結果為
utils 模組裡的__name__ 值為: __main__
第二步,執行main.py
python main.py
執行結果為
utils 模組裡的__name__ 值為: utils
輸入兩個整數,中間用空格分開:5 2
2.5
這裡有一個現象,你必須理解其背後的原因,我們明明執行的main.py指令碼,但是utils.py腳本里的程式碼也被執行了,這是因為在main.py腳本里引入了utils.py 這個模組,被引入的腳本里的程式碼會在引入時執行。
當utils.py 被其他指令碼引入時,它的__name__ 就不等於__main__, 而是等於utils,恰好是檔名稱去掉.py 剩餘的部分。
經過上面的實驗,我們可以得出兩個結論
1. 當指令碼被直接執行時,模組屬性__name__ 等於__main__
2. 當指令碼被其他模組引入時,模組屬性__name__ 等於指令碼名稱去掉.py 後剩餘的部分
3、終極目的---測試模組裡函式
由於一個指令碼被引入時,自身的程式碼會被執行,因此我們在每個腳本里都寫上一段if __name__ == '__main__': 如果你希望一些程式碼只有在指令碼被直接執行時才執行,那麼就把這些程式碼放入到if 語句塊中,最常見的情形就是測試程式碼,下面我對utils.py 進行修改
def safe_division(a, b):
if b == 0:
return None
return a/b
if __name__ == '__main__':
print(safe_division(10, 5) == 2)
print(safe_division(10, 0) == None)
我們寫完一個函式後,不免要寫一些測試的程式碼,而這些測試的程式碼我們不希望他們在utils.py被引入時執行,只有當我們主動執行utils.py 進行測試才執行這些測試程式碼
掃一掃,更多專業python技術分享