Python物件導向Python類別(Class)入門篇

在學習程式語言時,或多或少都有聽過物件導向程式設計(Object-oriented programming,簡稱OOP),它是一個具有物件(Object)概念的開發方式,能夠提高軟體的重用性、擴充性及維護性,在開發大型的應用程式時更是被廣為使用,所以在現今多數的程式語言都有此種開發方式,Python當然也不例外。而要使用物件導向程式設計就必須對類別(Class)及物件(Object)等有一些基本的了解,包含了:

  • 類別(Class)

  • 物件(Object)

  • 屬性(Attribute)

  • 建構式(Constructor)

  • 方法(Method)

我們先來看一下今天要來建立的類別:

1
2
3
4
5
6
7
8
9
# 汽車類別
class Cars:
    # 建構式
    def __init__(self, color, seat):
        self.color = color  # 顏色屬性
        self.seat = seat  # 座位屬性
    # 方法(Method)
    def drive(self):
        print(f"My car is {self.color} and {self.seat} seats.")

接下來就針對類別(Class)各個部分來進行介紹。

一、類別(Class)

簡單來說,就是物件(Object)的藍圖(blueprint)。就像要生產一部汽車時,都會有設計圖,藉此可以知道此類汽車會有哪些特性及功能,類別(Class)就類似設計圖,會定義未來產生物件(Object)時所擁有的屬性(Attribute)及方法(Method)。而定義類別的語法如下:

class classname
  statement

首先會有class關鍵字,接著自定類別名稱,最後加上冒號。類別名稱的命名原則習慣上使用Pascal命名法,也就是每個單字字首大寫,不得使用空白或底線分隔單字,如下範例:

1
2
3
4
範例一
class Cars:
#範例二
class MyCars:

二、物件(Object)

就是透過類別(Class)實際建立的實體,就像實際生產出來的汽車(例如:Mazda)。類別(Class)與物件(Object)的關係就像汽車設計圖與汽車實體。而建立物件(Object)的語法如下:

object_name = classname()

範例:

mazda = Cars() 

範例中的mazda即是Cars類別(Class)的物件(Object)。Python也提供了一個函式isinstance()來判斷類別(Class)與物件(Object)的關係,語法如下:

isinstance(object_name, class_name) 

範例:

# 汽車類別
class Cars:
    pass
# 摩托車類別
class Motorcycle:
    pass
# 建立Cars類別的物件
mazda = Cars()
print(isinstance(mazda, Cars))  # 執行結果:True
print(isinstance(mazda, Motorcycle))  # 執行結果:False

第15行由於mazda並不是Motorcycle的物件(Object),所以執行結果為False。

三、屬性(Attribute)

負責存放物件(Object)的資料。設定物件(Object)的屬性值語法如下:

object_name.attribute_name = value 

範例:

1
2
3
mazda = Cars()  # 建立Cars類別的物件 
mazda.color = "blue"  #顏色屬性 
mazda.seat = 4  #座位屬性

從範例中可以看到,建立物件(Object)後,才可進行屬性值(Attribute)的設定。但是這種寫法當有很多屬性需進行設定時,會顯得沒有效率,所以會建議使用建構式(Constructor)來進行屬性值(Attribute)的設定,於文章第四節會來跟大家說明。而存取物件的屬性值則透過以下語法:

object_name.attribute_name 

範例:

print(mazda.color)  # 執行結果:blue
print(mazda.seat)  # 執行結果:4

四、建構式(Constructor)

於建立物件(Object)的同時,會自動執行的方法(Method)。所以通常我們會在建構式(Constructor)中初始化物件(Object)的屬性值(Attribute)。至少要有一個self參數,之後利用逗號區隔其他屬性,語法如下:

1
2
3
4
# 建構式
def __init__(self, color, seat):
  self.color = color  # 顏色屬性
  self.seat = seat  # 座位屬性

而這個self是什麼意思呢?它代表了實體物件的參考,也就是目前的物件(Object)。這個self就是告訴類別(Class)目前是在設定哪一個物件的屬性(Attribute)。所以範例中的意思就是此物件的color屬性等於傳入的color屬性值,此物件的seat屬性等於傳入的seat屬性值,而傳入屬性值的方式就是在建立物件的時候,如下範例:

1
2
3
4
5
6
7
# 汽車類別
class Cars:
    # 建構式
    def __init__(self, color, seat):
        self.color = color  # 顏色屬性
        self.seat = seat  # 座位屬性
mazda = Cars("blue", 4)

範例中於建立mazda物件(Object)的同時,生成其屬性並且初始化屬性值(color和seat)。你一定會想說奇怪,建構式(Constructor)的參數有三個,為什麼我們只有傳入兩個?因為第一個self參數,Python編譯器會幫我們把目前物件的參考(mazda)傳給建構式(Constructor),所以我們就不需要多此一舉傳入物件。

五、方法(Method)

可以想像是物件(Object)的行為。定義方法(Method)和函式(Function)的語法很像,都是def關鍵字開頭,接著自訂名稱,但是方法(Method)和建構式(Constructor)一樣至少要有一個self參數,語法如下:

def method_name(self):
  statement

範例:

# 汽車類別
class Cars:
    # 建構式
    def __init__(self, color, seat):
        self.color = color  # 顏色屬性
        self.seat = seat  # 座位屬性
    # 方法(Method)
    def drive(self):
        print(f"My car is {self.color} and has {self.seat} seats.")
mazda = Cars("blue", 4)
mazda.drive()  #執行結果:My car is blue and has 4 seats.

方法(Method)的self參數同樣是代表目前的物件(mazda),在呼叫時Python編譯器會自動幫我們傳入。方法(Method)中透過self.color及self.seat的方式來存取目前物件(mazda)的color和seat屬性值,並且印出結果。

六、小結

以上就是Python類別(Class)的基本觀念介紹,希望透過此文章,可以大致瞭解整個Python類別(Class)的架構,並且有能力建立屬於自己的類別(Class)。當然其中的屬性(Attribute)又可分為:

  • 實體屬性(Instance Attribute)

  • 類別屬性(Class Attribute)

而方法(Method)也可分為:

  • 實體方法(Instance Method)

  • 類別方法(Class Method)

  • 靜態方法(Static Method)

結語

物件導向-Class類的封裝/繼承/多型

▍為什麼要學習物件導向設計原因:

  1. 使程式碼的維護和擴充更容易

  2. 使人更容易閱讀理解程式碼邏輯

▍本篇大綱

  1. 首先用 Class 來定義類別

  2. OOP 特性一. 繼承 (inheritance)

  3. OOP 特性二. 封裝 (encapsulation)

  4. OOP 特性三. 多型 (polymorphism)

  5. 補充:類的其他呼叫方式

首先用 Class 來定義類別

在物件導向中,類別是所有共同物件成員的抽象描述,它定義該類別物件共同具有的屬性,及實現該物件的方法。

Python 建立 class,通常類名採用大寫 (下面範例為 Employee ),在類中可以定義屬性和方法。

以下為簡單的 class 類範例:

1. self.working_hour = 0 為定義屬性

2. def work(self): 為定義方法

class Employee:
    def __init__(self):
        self.working_hour = 0 #屬性

    def work(self): #方法
        self.working_hour += 1
        print(Working:, working_hour)

andy = Employee()  # 類的實例化
andy.work() # 呼叫類的方法
print(andy.working_hour) # 呼叫類的屬性

▍Python class 自由度很高,定義屬性的三種方法

class ThisTestClass:
    getName = 'Max'  #方法一:把屬性定義寫在init外面

    def __init__(self):
        self.getNameFromInit = Max__init__  #方法二:把屬性定義寫在init內
        pass


if __name__ == __main__:

    task = ThisTestClass()
    task.sendName = Max_sendName  ##方法三:自己給屬性與參數

    print(task.getName)
    print(task.getNameFromInit)
    print(task.sendName)

>>> Max
>>> Max__init__
>>> Max_sendName

▍物件導向有三大基本特性,分別是:

  1. 封裝 (encapsulation)
  2. 繼承 (inheritance)
  3. 多型 (polymorphism)

特性一. 繼承 (inheritance)

▍簡單來說:繼承就像是生活中,子女繼承父母的財產一樣。

實作 class 繼承範例:首先 Employee 是這次的父親,而 Andy 是繼承 Employee 的孩子

  1. 程式範例第四行 class Andy(Employee),這邊讓 Andy 繼承 Employee物件

  2. 程式範例第六行 super().init(),這邊 super 是呼叫父類別的語法,所以繼承了父親的能力

  3. 程式範例第十行 print(‘tree:’, self.cut_tree),繼承後即可調用父親能力

而如果子類有與父類擁有同名的函式,則子類會會覆蓋掉父類的函式

class Employee:
    def __init__(self):
        self.cut_tree = 3

class Andy(Employee):
    def __init__(self, get_gold):
        super().__init__()
        self.get_gold = get_gold

    def getDetials(self):
        print('==getDetals==')
        print('tree:', self.cut_tree)
        print('gold:', self.get_gold)


if __name__ == "__main__":
    andy = Andy(1)
    andy.getDetials()

>>> tree: 3
>>> gold: 1

特性二. 封裝 (encapsulation)

▍簡單來說:隱藏程式實現細節只保留下接口,使程式容易模組化。

封裝從字面上理解就是包裝的意思,像是手機,從開機、打電話到上網我們都都不知道背後具題實現細節,但只需要按下按鈕就可以完成,這功能就是封裝。

以下範例 work() 就是封裝的表現,可以讓外部使用者不需考慮內部實作而直接呼叫使用。

若是有不想被呼叫的變數,直接在前面加上 __像是 __sleep即可以成為私有變數,如果使用者呼叫 __sleep 時則會噴 object has no attribute 的錯誤。

class Employee:
    def __init__(self):
        self.cut_tree = 3

    def work(self):
        print(Working)

    def __sleep(self):
        print(Sleeping)


if __name__ == __main__:
    Andy = Employee()

    andy.work()
    >>> Working

    andy.__sleep()
    >>> AttributeError: Employee object hasno attribute __sleep

特性三. 多型 (polymorphism)

▍簡單來說:呼叫同名的方法時,會得到不同的結果。

如下範例 Employee、Andy 和 Joy 類別都同時擁有 work 的方法,但呼叫 w.work()、w1.work()、w2.work() 時卻有各自的表現形態。Python 會根據呼叫的類別來決定要執行哪個方法實作,這就是多型的意思。

class Employee:
    def work(self):
        print(Employee work)

class Andy(Employee):
    def work(self):
        print(Andy work)

class Joy(Employee):
    def work(self):
        print(Joy work)


w = Employee()
w1 = Andy()
w2 = Joy()

w.work()
w1.work()
w2.work()

>>> Employee work
>>> Andy work
>>> Joy work

補充:類的其他呼叫方式

class Employee:
    ‘’’這是__doc__資訊'''
    def work(self):
        print(‘Employee work’)


w = Employee()

print(w.__doc__)
print(w.__class__)
print(Employee.__dict__)

>>> 這是__doc__資訊
>>> <class ‘__main__.Employee’>
>>> {‘__module__’: ‘__main__’, ‘__doc__’:’這是__doc__資訊’, ‘work’: <function Employee.work at 0x10c579598>, ‘__dict__’: <attribute ‘__dict__’ of ‘Employee’ objects>, ‘__weakref__’: <attribute’__weakref__’ of ‘Employee’ objects>}

jangowJP5TjQ3z202310108wbeoz

Edit

Pub: 31 Oct 2023 09:22 UTC

Edit: 31 Oct 2023 12:14 UTC

Views: 128