首頁>技術>

1. 第一個類面向物件的概念

設想一下,你如何開發下面這個遊戲:

很難想象,用簡單的字串,int, list等資料型別就能表達和開發出這麼複雜的遊戲(實際上是可以的,只是很麻煩)。

更好的做法是使用面嚮物件的技術。這個遊戲無非就是一個個物件互相打打殺殺!

程式設計是對現實世界的模擬,我們先來看看面向物件的幾個核心概念:

類 - 模板,如人類例項 - 用模板造出的物件,如貂蟬屬性 - 是特徵,如姓名方法 - 是行為,是技能,如攻擊

在早期的程式語言中,比如C語言中,是沒有面向物件的概念的,所有的程式,不管多麼複雜,都是用數字,字串等來表達的。那時候我們稱為面向過程程式設計。

面向過程程式設計:Procedure Oriented Programming 是一種以過程和任務為中心的程式設計思想。透過一系列具體的步驟操作相關的資料,實現軟體功能。

面向物件程式設計

Object Oriented Programming 是一種以物件為基礎的程式設計思想。把資料和操作封裝到物件中,透過物件一系列的互動,實現軟體功能。

下面我用一個小的例子帶你理解面向物件。

假設有兩條狗,他們分別有自己的名字,身高,血量和攻擊力。我們要模擬一條狗攻擊了另外一條狗。

面向過程的程式碼可能是這樣的
#表示狗的屬性dog1_name = '大黃'dog1_height = 0.7dog1_blood = 1.0dog1_power = 0.1dog2_name = '二黑'dog2_height = 0.7dog2_blood = 1.0dog2_power = 0.2#dog1攻擊dog2print('dog1 attacking dog2')dog2_blood = dog2_blood - dog1_power#dog2攻擊dog1print('dog2 attacking dog1')dog1_blood = dog1_blood - dog2_power

這顯然不好,如果有100條狗互相亂咬呢?

我們來看看面向物件的寫法:

面向物件的程式碼
#類是一個模板class Dog: #構造方法 def __init__(self, name, height, blood, power):  self.name = name  self.height = height  self.blood = blood  self.power = power def attack(self, dog2):  dog2.blood = dog2.blood - self.powerd1 = Dog('大黃', 0.7, 10, 3) #建立第1個例項d2 = Dog('二黑', 0.5, 10, 4) #建立第2個例項print(f'攻擊前:{d2.blood}')d1.attack(d2)print(f'攻擊後:{d2.blood}')
首先建立了一個Dog類,它包含了4個屬性,和一個方法。接下來,我們就像女媧造人一樣,用Dog類作為模板,構建出兩個狗d1和d2。然後d1攻擊了d2。

這雖然看起來程式碼比上面還長,但是程式碼很自然,更容易懂,更有“人性”。

如果我們要建立100個Dog,也很容易。把這100個Dog放到一個列表中也很方便。

下面我們來庖丁解牛,從零開始學習面向物件的核心概念。

2.構造方法和屬性

我們再回到前面的例子,從零開始,理解類的核心概念。

最簡單的類
#最簡單的類class Dog:  pass

這是一個最簡單的類,它裡面什麼都沒有,就像一個空白的信封。注意類的定義以class開頭,後面是類的名字,類名一般用大寫。

建立例項

雖然它什麼都沒有,但我們仍然可以用它來建立例項。

d1 = Dog()d2 = Dog()print(id(d1))print(id(d2))

建立例項透過使用類名加括號,有的類需要傳入引數。透過下面的列印可以看出d1和d2的記憶體地址不同,他們確實是不同的例項,在記憶體裡有自己獨立的房間。

Python是一個動態語言,我們可以給類動態的新增屬性:

d1.name = '旺財'print(d1.name)print(d2.name)  #報錯,因為d2沒有name屬性

正常情況下類不是空的,我們要求建立例項的時候就必須填寫必要的資訊,這樣才是一個有效的例項。

構造方法 init

我們建立例項的過程,會呼叫了一個叫做__init__的方法。前面的Dog中沒有init方法,它就給我們建立了一個空的物件出來。實際上Python呼叫了Object類的init方法,這個方法不需要傳任何引數,也不做任何事情。

現在我們給Dog類加上__init__方法:

#類是一個模板class Dog: #構造方法 def __init__(self, name, height, blood, power):  self.name = name  self.height = height  self.blood = blood  self.power = power

這時候如果再去建立Dog的例項,而不傳入引數就會報錯了:

d1 = Dog() #報錯,必須要傳入指定的引數

init函式的第一個引數永遠是self,表示當前物件,表示自己。後面的引數看我們自己的需要,我們希望Dog類有name, height, blood和power等幾個屬性,所以我們就加了這幾個引數。

現在來正常的建立兩個例項:

d1 = Dog('大黃', 0.7, 10, 3) #建立第1個例項d2 = Dog('二黑', 0.5, 10, 4) #建立第2個例項

建立例項的時候,不需要傳入第一個self引數,Python會自動傳入。我們只要傳入self後面的幾個引數就行。注意引數的順序。

self和屬性

這裡需要認識一下self:

self表示當前的例項。self只用在類的內部,在外部就直接使用變數名了,如d1,d2透過self.name='XXX'就給當前例項建立了一個名為name的屬性。不同例項的屬性的值是不同的。預設屬性

並不是所有的屬性都一定要在構造方法中傳入,比如我們規定:blood在建立的時候預設都是10,也就是滿血。

那麼就沒必要在init中傳入這個引數了。我們可以在init函式中設定預設的值為10。

class Dog: #構造方法 def __init__(self, name, height, power):  self.name = name  self.height = height  self.blood = 10  self.power = power
訪問和修改屬性在類的內部,透過self.xxx訪問屬性在類的外部,透過變數名 d1.xxx訪問屬性修改屬性,用賦值語句賦值即可:外部:d1.name = '大黃黃'。內部:self.name = '大黃黃'

8
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 第3節,CodeIgniter開發環境顯示報錯兩種配置方法