Python 類和物件初步入門
Python 語言在設計之初,就定位為一門面向物件的程式語言,“Python 中一切皆物件”就是對 Python 這門程式語言的完美詮釋。
類和物件是 Python 的重要特徵,相比其它面嚮物件語言,Python 很容易就可以創建出一個類和物件。同時,Python 也支援面向物件的三大特徵:封裝、繼承和多型。
在 Python 中 物件幾乎是無所不在的,我們之前學習的變數、資料、函式都是物件。
類僅僅充當圖紙的作用,本身並不能直接拿來用,而只有根據圖紙造出的實際物品(物件)才能直接使用。
因此,Python 程式中類的使用順序是這樣的:
- 建立(定義)類,也就是製作圖紙的過程;
- 建立類的例項物件(根據圖紙造出實際的物品),通過例項物件實現特定的功能。
1、定義只包含方法的類
在 Python 中要定義一個只包含方法的類。
語法格式如下:
class 類名:
def 方法1(self, 引數列表):
pass
def 方法2(self, 引數列表):
pass
方法的定義格式和之前學習過的函式幾乎一樣。
區別在於第一個引數必須是 self,self代表類的例項,而非類。
注意:類名的命名規則要符合大駝峰命名法,每個單詞的首字母大寫,其它字母小寫。
2、建立物件
當一個類定義完成之後,要使用這個類來建立物件。
語法格式如下:
物件變數 = 類名()
例項化類在其他程式語言中一般用關鍵字 new,但是在 Python 中並沒有這個關鍵字,類的例項化類似函式呼叫方式。
通常我們會把創建出來的物件叫做類的例項,建立物件的動作叫做例項化,物件的屬性叫做例項屬性,物件呼叫的方法叫做例項方法。
第一個面向物件程式
需求
定義一個貓類 Cat
定義兩個方法 eat 和 drink
class Cat: """這是一個貓類""" def eat(self): print("小貓愛吃魚") def drink(self): print("小貓在喝水") tom = Cat() tom.drink() tom.eat()
在面向物件開發中,引用的概念是同樣適用的!
在 Python 中使用類建立物件之後,tom 變數中仍然記錄的是物件在記憶體中的地址,也就是 tom 變數引用了新建的貓物件。
使用 print 輸出物件變數,預設情況下,是能夠輸出這個變數引用的物件是由哪一個類建立的物件,以及在記憶體中的地址(十六進位制表示)。
......
......
print(tom)
# <__main__.Cat object at 0x01A0CC30>
案例進階:根據一個類建立多個物件
class Cat:
"""這是一個貓類"""
def eat(self):
print("小貓愛吃魚")
def drink(self):
print("小貓在喝水")
# 建立貓物件
tom = Cat()
print(tom)
# <__main__.Cat object at 0x01D9CC30>
# 再建立一個貓物件
lazy_cat = Cat()
print(lazy_cat)
# <__main__.Cat object at 0x01DAF4F0>
那麼問題來了:tom 和 lazy_cat 是同一個物件嗎?
通過列印記憶體地址,就可以判斷,這2個不是同一個物件。
3、方法中的 self 引數
給物件增加屬性
在 Python 中,要給物件設定屬性,非常的容易,但是不推薦使用。
因為:物件屬性的封裝應該封裝在類的內部,只需要在類的外部的程式碼中直接通過設定一個屬性即可。
tom.name = "Tom"
...
lazy_cat.name = "大懶貓"
注意:這種方式雖然簡單,但是不推薦使用!
使用 self 在方法內部輸出每一隻貓的名字。
由哪一個物件呼叫的方法,方法內的 self 就是哪一個物件的引用。
在類封裝的方法內部,self 就表示當前呼叫方法的物件自己。呼叫方法時,程式設計師不需要傳遞 self 引數。
在方法內部可以通過 self 訪問物件的屬性,也可以通過 self 呼叫其他的物件方法。
改造程式碼如下:
class Cat:
def eat(self):
print("%s 愛吃魚" % self.name)
tom = Cat()
tom.name = "Tom"
tom.eat()
# Tom 愛吃魚
lazy_cat = Cat()
lazy_cat.name = "大懶貓"
lazy_cat.eat()
# 大懶貓 愛吃魚
看似好像沒什麼問題,但是如果程式碼改成先呼叫方法,再設定屬性。
tom = Cat()
tom.drink()
tom.eat()
tom.name = "Tom"
print(tom)
程式執行就會報錯:
# AttributeError: 'Cat' object has no attribute 'name'
# 屬性錯誤:'Cat' 物件沒有 'name' 屬性
所以,在日常開發中,不推薦在類的外部給物件增加屬性。如果在執行時,沒有找到屬性,程式會報錯。物件應該包含有哪些屬性,應該封裝在類的內部。
4、初始化方法
當使用 類名() 建立物件時,會自動執行以下操作:
- 為物件在記憶體中分配空間 —— 建立物件
- 為物件的屬性設定初始值 —— 初始化方法(init)
這個 初始化方法就是 __init__ 方法,__init__ 是物件的內建方法。
__init__ 方法是專門用來定義一個類具有哪些屬性的方法!
那麼我們現在就在 Cat 中增加 __init__ 方法,驗證該方法在建立物件時是否會被自動呼叫。
class Cat:
"""這是一個貓類"""
def __init__(self):
print("初始化方法")
cat = Cat()
# 初始化方法
在初始化方法內部定義屬性
在 __init__ 方法內部使用 self.屬性名 = 屬性的初始值 就可以定義屬性。
定義屬性之後,再使用 Cat 類建立的物件,都會擁有該屬性。
class Cat:
def __init__(self):
print("這是一個初始化方法")
# 定義用 Cat 類建立的貓物件都有一個 name 的屬性
self.name = "Tom"
def eat(self):
print("%s 愛吃魚" % self.name)
tom = Cat() # 這是一個初始化方法
tom.eat() # Tom 愛吃魚
初始化的同時設定初始值
在開發中,如果希望在建立物件的同時,就設定物件的屬性,可以對 __init__ 方法進行改造。
- 把希望設定的屬性值,定義成 __init__ 方法的引數。
- 在方法內部使用 self.屬性 = 形參 接收外部傳遞的引數。
- 在建立物件時,使用 類名(屬性1, 屬性2...) 呼叫。
class Cat:
def __init__(self, name):
self.name = name
tom = Cat("Tom")
lazy_cat = Cat("大懶貓")
使用內建函式 dir 傳入物件,可以檢視物件內的所有屬性及方法。利用好 dir() 函式,在學習時很多內容就不需要死記硬背了。