Python中 __init__的通俗解釋?

題主Python小白一枚,而且沒有編程背景,正在自學機器學習。目前努力嘗試把各種機器學習演算法用python來實現。

但是這兩天一直被__init__的用法卡住腳步,總是看不懂其使用方法,看了很多網上資料也沒弄清意思,所以希望有大神可以指教一下!謝謝!


強行裝個吧:定義類的時候,若是添加__init__方法,那麼在創建類的實例的時候,實例會自動調用這個方法,一般用來對實例的屬性進行初使化。比如:

class testClass:

def __init__(self, name, gender): //定義 __init__方法,這裡有三個參數,這個self指的是一會創建類的實例的時候這個被創建的實例本身(例中的testman),你也可以寫成其他的東西,比如寫成me也是可以的,這樣的話下面的self.Name就要寫成me.Name。

self.Name=name //通常會寫成self.name=name,這裡為了區分前後兩個是不同的東東,把前面那個大寫了,等號左邊的那個Name(或name)是實例的屬性,後面那個是方法__init__的參數,兩個是不同的)

self.Gender=gender //通常會寫成self.gender=gender

print(hello) //這個print(hello)是為了說明在創建類的實例的時候,__init__方法就立馬被調用了。

testman = testClass(neo,male) //這裡創建了類testClass的一個實例 testman, 類中有__init__這個方法,在創建類的實例的時候,就必須要有和方法__init__匹配的參數了,由於self指的就是創建的實例本身,self是不用傳入的,所以這裡傳入兩個參數。這條語句一出來,實例testman的兩個屬性Name,Gender就被賦值初使化了,其中Name是 neo,Gender 是male。

看圖的運行結果。我也剛學,大學接觸過編程,獻醜了,就匿名了。


根據問題描述,猜測你缺少的是面向對象的思想,你的問題也來源於此。class定義出來的是一個類,類有各種參數(屬性)和功能(方法)。

比如說你定義了一個類--"人",這個類有身高體重這樣的參數,也有吃飯睡覺寫字這種功能。你可以用這個類來創建出一個「張三」,再創建出一個「李四」,他們之間沒有關係,你也可以隨便設置他們的參數,讓他們做不同的事情。這就是一個類可以生成多個對象,而__init__簡單的來說,就是在用這個類創建一個新的對象時,該做點什麼,比如說「人」在剛被創建時,至少應該哭幾聲嘛。


當類被調用,實例化的第一步是創建實例對象。一旦對象創建了,Python檢查是否實現了__init__()方法。默認情況下,如果沒有定義(或覆蓋)特殊方法__init__(), 對實例不會施加任何特別的操作。任何所需的特定操作,都需要程序員實現__init__(),覆蓋它的默認行為。如果__init__()沒有實現,則返回它的對象,實例化過程完畢。

然而,如果__init__()已經被實現,那麼它將被調用,實例對象作為第一個參數(self)被傳遞進去,像標準方法調用一樣。調用類時,傳進的任何參數都交給了__init__()。實際中,你可以想像成這樣:把創建實例的調用當成是對構造器的調用。

總之,

(a) 你沒有通過調用 new 來創建實例,你也沒有定義一個構造器。是Python為你創建了對象;

(b) __init__(),是在解釋器為你創建 個實例後調用的第一個方法,在你開始使用它之前,這一步可以讓你做一些準備工作。

__init__()是很多為類定義的特殊方法之一。其中一些特殊方法是預定義的,預設情況下,不進行任何操作,比如__init__(),要定製,就必須對它進行重載,還有些方法,可能要按需要去實現。

——引自《Python核心編程》第二版

個人的理解是:

  1. 它為於類內部,可以讓你在裡面先做一些初始化工作,例如定義一些變數供後面的其它方法使用

  2. 只要其所在的類被實例化了,這個(特殊)方法就會被執行。 相對的,我們都知道,類裡面的方法,如果沒有被調用到,它是不會被執行到的,而這個(特殊)方法卻不需要明確調用即可被執行
  3. 不必太糾結,如果你不用它也能實現你想要的功能,那麼(至少在你目前的階段)可以先不去定義它

同為新手,一起交流,共同學習,如有錯誤,還忘新老司機們指正,小弟不勝感激!


直接理解成類初始化的時候,創造或者帶入一個或者幾個類的全局變數。


建議樓主可以看看python cookbook關於類的章節,簡單來說__init__方法並不像其他語言構造類實例,構造類實例是__new__方法,前者是類實例構造後觸發進行實例初始化方法,後者是實例構造前觸發所以它是構造方法,不過如果清楚,你可以把__init__當成初始化類屬性就好了。


謝邀

類代表了一類事物,這一類事物有一系列的屬性,當你在特指某個類的特定對象時,需要為他的這些屬性設定具體的值。這就是init的工作

舉個例子,假如題主你創建了一個"人類",那麼每個人都有的屬性可能有什麼呢,最簡單的,姓名,身高,體重,身份證號,出生年月。 好了,當你在特指人類的某個特定對象,編程中叫實例化,這裡就是你創造一個具體的人,那麼這個人的,姓名,身高,體重,身份證號,出生年月都得有具體的值,init就是幫你為每類事物的特定對象初始化這些屬性值的


面向對象最重要的概念就是類(Class)和實例(Instance),必須牢記類是抽象的模板,比如Student類,而實例是根據類創建出來的一個個具體的「對象」,每個對象都擁有相同的方法,但各自的數據可能不同。

仍以Student類為例,在Python中,定義類是通過class關鍵字:

class Student(object):
pass

class後面緊接著是類名,即Student,類名通常是大寫開頭的單詞,緊接著是(object),表示該類是從哪個類繼承下來的,繼承的概念我們後面再講,通常,如果沒有合適的繼承類,就使用object類,這是所有類最終都會繼承的類。

定義好了Student類,就可以根據Student類創建出Student的實例,創建實例是通過類名+()實現的:

&>&>&> bart = Student()
&>&>&> bart
&<__main__.Student object at 0x10a67a590&>
&>&>&> Student
&

可以看到,變數bart指向的就是一個Student的實例,後面的0x10a67a590是內存地址,每個object的地址都不一樣,而Student本身則是一個類。

可以自由地給一個實例變數綁定屬性,比如,給實例bart綁定一個name屬性:

&>&>&> bart.name = Bart Simpson
&>&>&> bart.name
Bart Simpson

由於類可以起到模板的作用,因此,可以在創建實例的時候,把一些我們認為必須綁定的屬性強制填寫進去。通過定義一個特殊的__init__方法,在創建實例的時候,就把name,score等屬性綁上去:

class Student(object):

def __init__(self, name, score):
self.name = name
self.score = score

注意:特殊方法「init」前後有兩個下劃線!!!

注意到__init__方法的第一個參數永遠是self,表示創建的實例本身,因此,在__init__方法內部,就可以把各種屬性綁定到self,因為self就指向創建的實例本身。

有了__init__方法,在創建實例的時候,就不能傳入空的參數了,必須傳入與__init__方法匹配的參數,但self不需要傳,Python解釋器自己會把實例變數傳進去:

&>&>&> bart = Student(Bart Simpson, 59)
&>&>&> bart.name
Bart Simpson
&>&>&> bart.score
59

和普通的函數相比,在類中定義的函數只有一點不同,就是第一個參數永遠是實例變數self,並且,調用時,不用傳遞該參數。除此之外,類的方法和普通函數沒有什麼區別,所以,你仍然可以用默認參數、可變參數、關鍵字參數和命名關鍵字參數。

數據封裝

面向對象編程的一個重要特點就是數據封裝。在上面的Student類中,每個實例就擁有各自的name和score這些數據。我們可以通過函數來訪問這些數據,比如列印一個學生的成績:

&>&>&> def print_score(std):
... print(%s: %s % (std.name, std.score))
...
&>&>&> print_score(bart)
Bart Simpson: 59

但是,既然Student實例本身就擁有這些數據,要訪問這些數據,就沒有必要從外面的函數去訪問,可以直接在Student類的內部定義訪問數據的函數,這樣,就把「數據」給封裝起來了。這些封裝數據的函數是和Student類本身是關聯起來的,我們稱之為類的方法:

class Student(object):

def __init__(self, name, score):
self.name = name
self.score = score

def print_score(self):
print(%s: %s % (self.name, self.score))

要定義一個方法,除了第一個參數是self外,其他和普通函數一樣。要調用一個方法,只需要在實例變數上直接調用,除了self不用傳遞,其他參數正常傳入:

&>&>&> bart.print_score()
Bart Simpson: 59

這樣一來,我們從外部看Student類,就只需要知道,創建實例需要給出name和score,而如何列印,都是在Student類的內部定義的,這些數據和邏輯被「封裝」起來了,調用很容易,但卻不用知道內部實現的細節。

封裝的另一個好處是可以給Student類增加新的方法,比如get_grade:

class Student(object):
...

def get_grade(self):
if self.score &>= 90:
return A
elif self.score &>= 60:
return B
else:
return C

轉自廖雪峰老師的博客


e.g.

class Example:

def __init__(self, a, b):

self.parm1 = a

self.parm2 = b

...

zhihu = Example(1, 2)

# zhihu.parm1 = 1

# zhihu.parm2 = 2


剛好在寫Python的總結寫到這塊,強行答一波,本人也是Python小白:

以下內容為節選:

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

class關鍵字後面跟類的名稱就定義了一個類,類的名稱可以任意,採用駝峰命名法,也即每個單詞的首字母大寫,如Book、Person、WildAnimal等

這裡的__init__方法是一個特殊的方法(init是單詞初始化initialization的省略形式),在使用類創建對象之後被執行,用於給新創建的對象初始化屬性用。

初始化屬性的語句就是self.name = name這種了,這一句不太好理解,我們把它改編一下就好理解了:

def __init__(self, n, a):
self.name = n
self.age = a

首先這是一個方法,方法的形參有self,n和a三個。

這個self,表示對象本身,誰調用,就表示誰(這句話不好理解,先記住,我們後面分析)。

語法上,類中的方法的第一個參數都是self,這是和普通方法區別的地方。

這裡self.name = nself.age = a表示將外部傳來的n和a,賦值給了self對象的name和age屬性。

這裡的n和a,其實叫什麼都可以,但是會有個問題:一般我們調用方法的時候,想自動提示一下或者查看文檔看一下這個方法的參數要求,如果形參名都是n、a、m、i這些,會讓人摸不著頭腦,不知道到底該傳入什麼樣的實參。因為這裡我們傳入實參是為了給屬性賦值,為了能見名知意,將形參的名字定義的跟屬性一致,調用者就知道該怎麼傳參了。

所以才有了上面的寫法。

再來說創建對象:

p = Person(小明, 20)

這句話就創建出來了一個具體的人,並且給這個人起了個名字叫小明,指定了小明的年齡為20,並且將小明這個對象賦值給了變數p,此時p就表示小明這個人(對象)

這就造出了一個人。

既然你是神,當然想造出什麼樣的人都可以,比如造出一個200歲的叫傑拉考的人:

p = Person(傑拉考, 200)

這句話後面的Person(傑拉考, 200)用於創建出了一個對象(人),並且調用了init(self,name,age)方法完成了該人的屬性的初始化,傑拉考賦值給了name200賦值給了age屬性。

self呢?self不需要傳參,上面我們說過,self,表示對象本身,誰調用,就表示誰,此時的self就表示你Person(傑拉考, 200)創造出來的那個對象,也即是p

也即,我們創造出了p,然後給p的屬性賦了值,此時p就表示擁有屬性值之後的那個人。

可以使用點.來調用對象的屬性,比如輸出p的名字和年齡,完整代碼為:

class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person(傑拉考, 200)
print(p.name)
print(p.age)

輸出結果:

傑拉考
200

接下來我們再在Person類中定義一個方法,用於自我介紹:

def desc(self):
print("我叫%s,今年%d歲" % (self.name, self.age))

在類的內部,訪問自己的屬性和方法,都需要通過self,self就是外部對象在類內部的表示,此時可以使用p調用該方法,完整代碼如下:

class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def desc(self):
print("我叫%s,今年%d歲" % (self.name, self.age))
p = Person(傑拉考, 200)
# 調用自我介紹方法 desc方法中的self就是外部的這個p
p.desc()

輸出為:

我叫傑拉考,今年200歲

當前desc方法中的self,就是外部的那個對象p,如果我再定義了一個對象p2,那麼p2調用desc時,desc中的self就表示p2這個對象。正所謂:誰調用,就表示誰


這麼來說吧,就好像你創建一個遊戲角色的時候只要輸入角色名,系統就會幫你創建這個角色,但這個角色除了你給的名字外還有其它的屬性,這些屬性就是這個init方法裡面做的事


那肯定就不說構造函數,或者構造器啦!

初始化類中的變數,供類中的函數間調用。

其主要作用還是傳參,py3和2有差別的,在學習過程中發現2中的方法在3中不能用,去看cookbook,或者一些大牛的筆記@vamei

http://www.cnblogs.com/vamei/


類和實例

參考這篇文章,廖雪峰python教程。簡單明了。


最重要的一點…

init的意思是:initialize,初始化,因此可以理解實例化出某個類的對象時調用的初始化方法。


如果說構造器的話,還得加上__new__


你可以理解為java或c++中的構造方法。


推薦閱讀:

Python GUI教程(一):在PyQt5中創建第一個GUI圖形用戶界面
python的list是數組的結構還是鏈表的結構?
喵哥的Django學習筆記1:安裝
python根據BM25實現文本檢索
深入描述符

TAG:Python | 機器學習 |