1. 程式人生 > 實用技巧 >Python 類和物件初步入門

Python 類和物件初步入門

Python 語言在設計之初,就定位為一門面向物件的程式語言,“Python 中一切皆物件”就是對 Python 這門程式語言的完美詮釋。

類和物件是 Python 的重要特徵,相比其它面嚮物件語言,Python 很容易就可以創建出一個類和物件。同時,Python 也支援面向物件的三大特徵:封裝、繼承和多型。

在 Python 中 物件幾乎是無所不在的,我們之前學習的變數、資料、函式都是物件。

類僅僅充當圖紙的作用,本身並不能直接拿來用,而只有根據圖紙造出的實際物品(物件)才能直接使用。

因此,Python 程式中類的使用順序是這樣的:

  1. 建立(定義)類,也就是製作圖紙的過程;
  2. 建立類的例項物件(根據圖紙造出實際的物品),通過例項物件實現特定的功能。

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、初始化方法

當使用 類名() 建立物件時,會自動執行以下操作:

  1. 為物件在記憶體中分配空間 —— 建立物件
  2. 為物件的屬性設定初始值 —— 初始化方法(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__ 方法進行改造。

  1. 把希望設定的屬性值,定義成 __init__ 方法的引數。
  2. 在方法內部使用 self.屬性 = 形參 接收外部傳遞的引數。
  3. 在建立物件時,使用 類名(屬性1, 屬性2...) 呼叫。
class Cat:

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

tom = Cat("Tom")
lazy_cat = Cat("大懶貓")

使用內建函式 dir 傳入物件,可以檢視物件內的所有屬性及方法。利用好 dir() 函式,在學習時很多內容就不需要死記硬背了。