Python中if __name__ == '__main__',__init__和self 的解析
文章推薦指數: 80 %
Python中if __name__ == '__main__',__init__和self 的解析 ... 不管是直接執行還是被匯入,.py檔案的最頂層程式碼都會被執行(Python用縮排來區分 ...
MdEditor
Python中if__name__=='__main__',__init__和self的解析
語言:CN/TW/HK
時間 2020-09-2919:25:26
洋仔
主題:
掘金
稀土
Vue.js
微信小程式
Kotlin
RxJava
ReactNative
Wireshark
敏捷開發
Bootstrap
OKHttp
正則表示式
WebGL
Webpack
Docker
MVVM
文章主要包括2部分內容,分別是ifname=='main'的解析和init與self的解析。
目錄
1ifname=='main'
1.1摘要
1.2程式入口
1.2.1一個.py檔案被其他.py檔案引用
1.2.2修改const.py,新增ifname=="main"
2init與self
2.1Python中self的含義
2.2Python中為何要有self
2.3首先來看一下init()和self物件
2.4如果沒有在init中初始化對應的例項變數的話,導致後續引用例項變數會出錯
2.5在函式中,使用對應的變數,雖然程式碼是可以執行的,但是實際上使用的,不是例項中的變數
1ifname=='main'
1.1摘要
通俗的理解name=='main':假如你叫小明.py,在朋友眼中,你是小明(name=='小明');在你自己眼中,你是你自己(name=='main')。
ifname=='main'的意思是:當.py檔案被直接執行時,ifname=='main'之下的程式碼塊將被執行;當.py檔案以模組形式被匯入時,ifname=='main'之下的程式碼塊不被執行。
1.2程式入口
對於很多程式語言來說,程式都必須要有一個入口,比如C,C++,以及完全面向物件的程式語言Java,C#等。
如果你接觸過這些語言,對於程式入口這個概念應該很好理解,C,C++都需要有一個main函式作為程式的入口,也就是程式的執行會從main函式開始。
同樣,Java,C#必須要有一個包含Main方法的主類,作為程式入口。
而Python則不同,它屬於指令碼語言,不像編譯型語言那樣先將程式編譯成二進位制再執行,而是動態的逐行解釋執行。
也就是從指令碼第一行開始執行,沒有統一的入口。
一個Python原始碼檔案(.py)除了可以被直接執行外,還可以作為模組(也就是庫),被其他.py檔案匯入。
不管是直接執行還是被匯入,.py檔案的最頂層程式碼都會被執行(Python用縮排來區分程式碼層次),而當一個.py檔案作為模組被匯入時,我們可能不希望一部分程式碼被執行。
1.2.1一個.py檔案被其他.py檔案引用
假設我們有一個const.py檔案,內容如下:
PI=3.14
defmain():
print("PI:",PI)
main()
執行結果:PI:3.14
現在,我們寫一個用於計算圓面積的area.py檔案,area.py檔案需要用到const.py檔案中的PI變數。
從const.py中,我們把PI變數匯入area.py:
fromconstimportPI
defcalc_round_area(radius):
returnPI*(radius**2)
defmain():
print("roundarea:",calc_round_area(2))
main()
'''
執行結果:
PI:3.14
roundarea:12.56
'''
1.2.2修改const.py,新增ifname=="main"
我們看到const.py中的main函式也被運行了,實際上我們不希望它被執行,因為const.py提供的main函式只是為了測試常量定義。
這時ifname=='main'派上了用場,我們把const.py改一下,新增ifname=="main":
PI=3.14
defmain():
print("PI:",PI)
ifname=="main":
main()
執行const.py,輸出如下:
PI:3.14
執行area.py,輸出如下:
roundarea:12.56
如上,我們可以看到ifname=='main'相當於Python模擬的程式入口,Python本身並沒有這麼規定,這只是一種編碼習慣。
由於模組之間相互引用,不同模組可能有這樣的定義,而程式入口只有一個。
到底哪個程式入口被選中,這取決於name的值。
2init與self
2.1Python中self的含義
self,英文單詞意思很明顯,表示自己,本身。
python的self,是個物件(Object),是當前類的例項。
2.2Python中為何要有self
那就是:
在類的程式碼(函式)中,需要訪問當前的例項中的變數和函式的,即,訪問Instance中的:
對應的變數(屬性,property):Instance.ProperyNam,去讀取之前的值和寫入新的值
呼叫對應函式(function):Instance.function(),即執行對應的動作
->而需要訪問例項的變數和呼叫例項的函式,當然需要對應的例項Instance物件本身
->而Python中就規定好了,函式的第一個引數,就必須是例項物件本身,並且建議,約定俗成,把其名字寫為self
->所以,我們需要self
而如果沒有用到self,即程式碼中,去掉self後,那種寫法所使用到的變數,實際上不是你所希望的,不是真正的例項中的變數和函式,而是的訪問到了其他部分的變數和函數了。
甚至會由於沒有合適的初始化例項變數,而導致後續無法訪問的錯誤。
下面,就通過程式碼,來演示,如果去掉self,或者沒有合理的使用self,會出現哪些錯誤。
2.3首先來看一下init()和self物件
#!/usr/bin/envpython
--coding:utf-8--
classPerson(object):
definit(self,name,lang,website):
self.name=name
self.lang=lang
self.website=website
print('self:',self)
print('typeofself:',type(self))
複製程式碼
'''
未例項化時,執行程式,構造方法沒有執行
'''
p=Person('Tim','English','www.universal.com')
'''例項化後執行的結果
self:
classDog(object):
definit(self,name,dog_type):
self.name=name
self.type=dog_type
defsayhi(self):
print("hello,Iamadog,mynameis",self.name)
複製程式碼
d=Dog('LiChuang',"京巴")#例項化
d.sayhi()
以下是d=Dog('LiChuang',"京巴")例項化的示意圖:
2.4如果沒有在init中初始化對應的例項變數的話,導致後續引用例項變數會出錯
如下程式碼,完整的演示了,如果沒有在類Class的最初的init函式中,正確的初始化例項變數,則會導致後續沒有變數可用,因而出現AttributeError的錯誤:
#!/usr/bin/envpython
--coding:utf-8--
name='wholeglobalname'
'''
注:此處全域性的變數名,寫成name,只是為了演示而用
實際上,好的程式設計風格,應該寫成gName之類的名字,
以表示該變數是Global的變數
'''
classPerson(object):
definit(self,newPersonName):
#self.name=newPersonName
'''
如果此處不寫成self.name
那麼此處的name,只是__init__函式中的區域性臨時變數name而已
和全域性中的name,沒有半毛錢關係
'''
name=newPersonName
'''
此處只是為了程式碼演示,而使用了局部變數name,
不過需要注意的是,此處很明顯,由於接下來的程式碼也沒有利用到此處的區域性變數name
則就導致了,此處的name變數,實際上被浪費了,根本沒有利用到
'''
defsayYourName(self):
'''
此處由於找不到例項中的name變數,所以會報錯:
AttributeError:Personinstancehasnoattribute'name'
'''
print('Mynameis%s'%self.name)
複製程式碼
defselfAndInitDemo():
personInstance=Person('Tim')
personInstance.sayYourName()
ifname=='main':
selfAndInitDemo()
'''未使用self.name時拋異常
Traceback(mostrecentcalllast):
File"E:/python14_workspace/s14/day06/test_1.py",line18,in
selfAndInitDemo()
File"E:/python14_workspace/s14/day06/test_1.py",line15,inselfAndInitDemo
personInstance.sayYourName()
File"E:/python14_workspace/s14/day06/test_1.py",line11,insayYourName
print('Mynameis%s'%self.name)
AttributeError:'Person'objecthasnoattribute'name'
'''
從上述程式碼可見,由於在類的初始化(例項化)的init函式中,沒有給self.name設定值,使得例項中,根本沒有name這個變數,導致後續再去訪問self.name,就會出現AttributeError的錯誤了。
對應的,如果寫成self.name,則意思就正確了,就是初始化的時候,給例項中新增加,並且正常設定了正確的值newPersionName了,所以後續再去通過self.name,就可以訪問到,當前例項中正確的變數name了。
相應的正確寫法的程式碼如下:
#!/usr/bin/envpython
--coding:utf-8--
name='wholeglobalname'
'''
注:此處全域性的變數名,寫成name,只是為了演示而用
實際上,好的程式設計風格,應該寫成gName之類的名字,
以表示該變數是Global的變數
'''
classPerson(object):
definit(self,newPersonName):
self.name=newPersonName
'''
此處正確的,通過訪問self.name的形式,實現了:
1.給例項中,增加了name變數
2.並且給name賦了初值,為newPersionName
'''
defsayYourName(self):
'''
此處由於開始正確的初始化了self物件,使得其中有了name變數,
所以此處可以正確訪問了name值了
'''
print('Mynameis%s'%self.name)
defselfAndInitDemo():
personInstance=Person('Tim')
personInstance.sayYourName()
ifname=='main':
selfAndInitDemo()
'''MynameisTim'''
2.5在函式中,使用對應的變數,雖然程式碼是可以執行的,但是實際上使用的,不是例項中的變數
有時候,雖然你寫的程式碼,可以執行,但是使用到的變數,由於沒有加self,實際上是用到的不是例項的變數,而是其他的變數。
此類問題,主要和Python中的變數的作用域有關,但是此處例子中,也和是否使用self有關:
#!/usr/bin/envpython
--coding:utf-8--
name='wholeglobalname'
'''
注:此處全域性的變數名,寫成name,只是為了演示而用
實際上,好的程式設計風格,應該寫成gName之類的名字,
以表示該變數是Global的變數
'''
classPerson(object):
name='classglobalname'
def__init__(self,newPersonName):
#self.name=newPersonName
'''
此處,沒有使用self.name
而使得此處的name,實際上仍是區域性變數name
雖然此處賦值了,但是後面沒有被利用到,屬於被浪費了的區域性變數name
'''
name=newPersonName
defsayYourName(self):
'''
此處,之所以沒有像之前一樣出現:
AttributeError:Personinstancehasnoattribute'name'
那是因為,雖然當前的例項self中,沒有在__init__中初始化對應的name變數,例項self中沒有對應的name變數
但是由於例項所對應的類Person,有對應的name變數,所以也是可以正常執行程式碼的
對應的,此處的self.name,實際上是Person.name
'''
print('Mynameis%s'%self.name)
print('NamewithinclassPersonisactuallytheglobalname:%s'%name)
print("OnlyaccessPerson'snameviaPerson.name=%s"%(Person.name))
複製程式碼
defselfAndInitDemo():
personInstance=Person('Tim')
personInstance.sayYourName()
print('wholeglobalnameis%s'%name)
ifname=='main':
selfAndInitDemo()
'''
Mynameisclassglobalname
NamewithinclassPersonisactuallytheglobalname:wholeglobalname
OnlyaccessPerson'snameviaPerson.name=classglobalname
wholeglobalnameiswholeglobalname
'''
其中,可見,此處開始init中,沒有給self例項初始化對應的name,
而後面的函式sayYourName中,雖然可以呼叫到self.name而沒有出現AttributeError錯誤,
但是實際上此處的值,不是所期望的,傳入的name,即"Tim",而是類中的name的值,即"classglobalname"。
「其他文章」
git基本原理詳解
@StateObject和@ObservedObject的區別和使用
SwiftProtobuf的源頭Protobuf是什麼
SwiftUI-DataBinding註解
講講SwiftUI的資料流向,@State,@Binding的區別
ReactNative執行原理解析
圖解JanusGraph系列-JanusGraph指標監控報警(MonitoringJanusGraph)
圖解JanusGraph系列-JanusGraph指標監控報警(MonitoringJanusGraph
程式設計之美!從執行緒池狀態管理來看二進位制操作之美
程式設計之美!從執行緒池狀態管理來看二進位制操作之美
圖解JanusGraph系列-關於JanusGraph圖資料批量快速匯入的方案和想法(bulkloaddata)
圖解Janusgraph系列-圖資料底層序列化原始碼分析(DataSerialize)
圖解Janusgraph系列-併發安全:鎖機制(本地鎖分散式鎖)分析
圖解Janusgraph系列-併發安全:鎖機制(本地鎖分散式鎖)分析
Webpack構建工具
Python中if__name__=='__main__',__init__和self的解析
Flask-SQLAlchemy詳解
「掘金」
商用清潔機器人江湖:16位創業者「同臺競技」
功能管理(Featuremanagement)中的Keystone模式
美團簡單版動態執行緒池原始碼實現
基於SvelteUi中後臺解決方案SvelteAdmin
記一次圖片中繁體文字轉簡體的嘗試
復刻一個羊了個羊掘金商城版
Elasticsearch:分詞器中的token過濾器使用示例
終於,掘金也有人講傅立葉變換了
【melonJS】幾十行JS程式碼簡單編寫一個小遊戲「尋找掘金醬」
神馬?要退役JavaScript?!誰人出此狂言?!
「稀土」
再被拒,就不禮貌了:《非正式面試》第一期上線!陪你度過秋招季
功能管理(Featuremanagement)中的Keystone模式
美團簡單版動態執行緒池原始碼實現
基於SvelteUi中後臺解決方案SvelteAdmin
記一次圖片中繁體文字轉簡體的嘗試
Elasticsearch:分詞器中的token過濾器使用示例
如果稀土掘金App要更新“釋出文章”功能,那麼入口會設定在哪裡?
企業級GIT分支管控方案
[極致使用者體驗]讓你的網頁,適配微信大字號模式!體驗超好,快來收藏
英特爾XDC2022精彩回顧:共建開放生態,釋放“基建”潛能
延伸文章資訊
- 1簡易理解python中的if __name__ == 'main' 的作用和原理
從學到python以來,常常看到很多函式(function)中出現以下的語句 if __name__ == '__main__': 雖然一直知道他是用來做甚麼的,但是卻不太能理解他的 ...
- 2Python中if __name__ == '__main__',__init__和self 的解析
Python中if __name__ == '__main__',__init__和self 的解析 ... 不管是直接執行還是被匯入,.py檔案的最頂層程式碼都會被執行(Python用縮排來區...
- 3Python中if __name__ == '__main__',__init__和self 的解析
Python中if __name__ == '__main__',__init__和self 的解析. anshuai_aw1 于 2018-09-03 10:32:21 发布 94322 收藏...
- 4What is __init__ == “__main__” in Python - Medium
A module can define functions, classes and variables. So when the interpreter runs a module, the ...
- 5Python中__main__和__init__ 的解析 - 知乎专栏
正确题目应该是Python中if __name__ == '__main__',__init__和self 的解析。 ... 如果没有在__init__中初始化对应的实例变量的话,导致后续引用实...