Python 中__init__函式以及引數self
Java網站連結:Java全棧工程師 | 以例項驅動學習 | how2j.cn
1)class類包含:
類的屬性:類中所涉及的變數
類的方法:類中函式
2) __init函式(方法)
1、帶有兩個下劃線開頭的函式是宣告該屬性為私有,不能在類地外部被使用或直接訪問。
2、init函式(方法)支援帶引數的類的初始化,也可以為宣告該類的屬性
3、init函式(方法)的第一個引數必須是self(self為習慣用法,也可以用別的名字),後面的引數則可以自由定義,和定義函式沒有任何區別。(釋:self,英文單詞意思很明顯,表示自己,本身)。此處有幾種潛在的含義:
1、這裡的自己,指的是,例項Instance本身。
2、同時,由於說到“自己”這個詞,都是和相對而言的“其他”而說的。而此處的其他,指的是,類Class,和其他變數,比如佈局變數,全域性變數。此處的self,是個物件,Object。是當前類的例項。
因此,對應的
self.valueName
self.fuction()中的
valueName:表示self物件,即例項的變數。與其他的,Class的變數,全域性的變數,區域性的變數,是相對應的。
function:表示是呼叫的是self物件,即例項的函式。與其他的全域性的函式,是相對應的。
Python中為何要有self
上面其實已經基本上說清楚了,為何需要有self。
那就是:
在類的程式碼(函式)中,需要訪問當前的例項中的變數和函式的,即,訪問Instance中的:
-
對應的變數(property):Instance.ProperyNam,去讀取之前的值和寫入新的值
-
呼叫對應函式(function):Instance.function(),即執行對應的動作
-> 而需要訪問例項的變數和呼叫例項的函式,當然需要對應的例項Instance物件本身
-> 而Python中就規定好了,函式的第一個引數,就必須是例項物件本身,並且建議,約定俗成,把其名字寫為self
-> 所以,我們需要self(需要用到self)
而如果沒有用到self,即程式碼中,去掉self後,那種寫法所使用到的變數,實際上不是你所希望的,不是真正的例項中的變數和函式,而是的訪問到了其他部分的變數和函式了。
甚至會由於沒有合適的初始化例項變數,而導致後續無法訪問的錯誤。
下面,就通過程式碼,來演示,如果去掉self,或者沒有合理的使用self,會出現哪些錯誤。
如果沒有在__init__中初始化對應的例項變數的話,導致後續引用例項變數會出錯
如下程式碼,完整的演示了,如果沒有在類Class的最初的__init__函式中,正確的初始化例項變數,則會導致後續沒有變數可用,因而出現AttributeError的錯誤:
#注:此處全域性的變數名,寫成name,只是為了演示而用
#實際上,好的程式設計風格,應該寫成gName之類的名字,以表示該變數是Global的變數
name = "whole global name";
class Person:
def __init__(self, newPersionName):
#self.name = newPersionName;
#1.如果此處不寫成self.name
#那麼此處的name,只是__init__函式中的區域性臨時變數name而已
#和全域性中的name,沒有半毛錢關係
name = newPersionName;
#此處只是為了程式碼演示,而使用了區域性變數name,
#不過需要注意的是,此處很明顯,由於接下來的程式碼也沒有利用到此處的區域性變數name
#則就導致了,此處的name變數,實際上被浪費了,根本沒有利用到
def sayYourName(self):
#此處由於找不到例項中的name變數,所以會報錯:
#AttributeError: Person instance has no attribute 'name'
print 'My name is %s'%(self.name);
def selfAndInitDemo():
persionInstance = Person("crifan");
persionInstance.sayYourName();
###############################################################################
if __name__=="__main__":
selfAndInitDemo();
從上述程式碼可見,由於在類的初始化(例項化)的__init__函式中,沒有給self.name設定值,使得例項中,根本沒有name這個變數,導致後續再去訪問self.name,就會出現AttributeError的錯誤了。
對應的,如果寫成self.name,則意思就正確了,就是初始化的時候,給例項中新增加,並且正常設定了正確的值newPersionName了,所以後續再去通過self.name,就可以訪問到,當前例項中正確的變數name了。
相應的正確寫法的程式碼如下:
#注:此處全域性的變數名,寫成name,只是為了演示而用
#實際上,好的程式設計風格,應該寫成gName之類的名字,以表示該變數是Global的變數
name = "whole global name";
class Person:
def __init__(self, newPersionName):
#此處正確的,通過訪問self.name的形式,實現了:
#1.給例項中,增加了name變數
#2.並且給name賦了初值,為newPersionName
self.name = newPersionName;
def sayYourName(self):
#此處由於開始正確的初始化了self物件,使得其中有了name變數,所以此處可以正確訪問了name值了,可以正確的輸出了:
#My name is crifan
print 'My name is %s'%(self.name);
def selfAndInitDemo():
persionInstance = Person("crifan");
persionInstance.sayYourName();
###############################################################################
if __name__=="__main__":
selfAndInitDemo();
在函式中,使用對應的變數,雖然程式碼是可以執行的,但是實際上卻是使用的,不是例項中的變數
有時候,雖然你寫的程式碼,可以執行,但是使用到的變數,由於沒有加self,實際上是用到的不是例項的變數,而是其他的變數。
此類問題,主要和Python中的變數的作用域有關,但是此處例子中,也和是否使用self有關:
#注:此處全域性的變數名,寫成name,只是為了演示而用
#實際上,好的程式設計風格,應該寫成gName之類的名字,以表示該變數是Global的變數
name = "whole global name";
class Person:
name = "class global name"
def __init__(self, newPersionName):
#self.name = newPersionName;
#此處,沒有使用self.name
#而使得此處的name,實際上仍是區域性變數name
#雖然此處賦值了,但是後面沒有被利用到,屬於被浪費了的區域性變數name
name = newPersionName;
def sayYourName(self):
#此處,之所以沒有像之前一樣出現:
#AttributeError: Person instance has no attribute 'name'
#那是因為,雖然當前的例項self中,沒有在__init__中初始化對應的name變數,例項self中沒有對應的name變數
#但是由於例項所對應的類Person,有對應的name變數,所以也是可以正常執行程式碼的
#對應的,此處的self.name,實際上是Person.name
print 'My name is %s'%(self.name); # -> class global name
print 'name within class Person is actually the global name: %s'%(name); #-> whole global name
print "only access Person's name via Person.name=%s"%(Person.name); # -> class global name
def selfAndInitDemo():
persionInstance = Person("crifan");
persionInstance.sayYourName();
print "whole global name is %s"%(name); # -> whole global name
###############################################################################
if __name__=="__main__":
selfAndInitDemo();
其中,可見,此處開始__init__中,沒有給self例項初始化對應的name
而後面的函式sayYourName中,雖然可以呼叫到self.name而沒有出現AttributeError錯誤
但是實際上此處的值,不是所期望的,傳入的name,即"crifan",而是類中的name的值,即"class global name"。
Python中的__init__
Python中,常會看到,很多類中,都有一個__init__函式。
下面就來解釋一下,__init__的含義。
Python中__init__的含義
首先來看init單詞本身,其含義是 初始化。
而__init__的含義,也如同其單詞本意一樣,用來初始化。
但是給誰初始化呢?
很明顯,是給對應的類Class本身,去初始化。
Python中為何要有__init__
我的理解是,__init__的出現,主要有兩方面的作用:
一般常見的初始化,我的理解,可能主要有兩方面:
支援帶引數的類的初始化
這個用法,感覺就像,其他語言中的,對於Class初始化時,可以執行傳遞不同的引數一樣;
用程式碼演示如下:
class Person:
def __init__(self, newPersionName):
#在開始初始化新的類Class的示例Instance的時候,給對應的,不同的Instance,設定不同的人名(Person name)
self.name = newPersionName;
def sayYourName(self):
#不同的Person的示例,呼叫同樣的方法的時候,說出自己的名字,結果都是對應著自己的,各自不同的名字
print 'My name is %s'%(self.name); #My name is crifan
def initDemo():
persionInstance = Person("crifan");
persionInstance.sayYourName();
###############################################################################
if __name__=="__main__":
initDemo();
相關文章
- Python 序列型別以及函式引數型別Python型別函式
- Python print函式引數詳解以及效果展示Python函式
- python中函式的引數傳遞Python函式
- Python 中的 super(類名, self).__init__() 的含義Python
- python---函式引數、變數Python函式變數
- Python函式引數總結Python函式
- python函式變長引數Python函式
- 一文看懂 Python 中的函式引數Python函式
- Python函式/動態引數/關鍵字引數Python函式
- python sorted()函式的引數用法Python函式
- 程式中的函式引數函式
- 函式中引數傳值函式
- 函式引數 引數定義函式型別函式型別
- 類中的__init__()和__call__()函式函式
- 1分鐘掌握 Python 函式引數Python函式
- python基礎之 函式的引數Python函式
- python不定長引數如何呼叫函式?Python函式
- Python中函式為什麼可以當做引數使用?Python函式
- 揭秘 Go 中的函式引數Go函式
- Python函式的位置引數、關鍵字引數精講Python函式
- 詳解Python魔法函式,__init__,__str__,__del__Python函式
- python變數中self的新增Python變數
- Python中將函式作為另一個函式的引數傳入並呼叫Python函式
- Python語法—函式及引數傳遞Python函式
- 『無為則無心』Python函式 — 26、Python函式引數的傳遞方式Python函式
- Javascript函式引數求值——Thunk函式JavaScript函式
- 函式基礎和函式引數函式
- Python3之函式的引數傳遞與引數定義Python函式
- Python的函式引數傳遞:傳值?引用?Python函式
- Python技法2:函式引數的進階用法Python函式
- Python函式引數和註解是什麼Python函式
- OpenCV中的findContours函式引數詳解OpenCV函式
- 函式、引數、解構函式
- 函式引數詳解函式
- 3.3.2 函式的預設引數和佔位引數 函式過載函式
- Python中__init__的理解Python
- Go 之基礎速學 (五) golang 裡函式以及函式之間引數的傳遞Golang函式
- 『無為則無心』Python函式 — 29、Python變數和引數傳遞Python函式變數