Python認識物件類別Class

Table of Contents

Table of Contents

物件導向設計是程式設計中一項重要的概念。 而Python語言中的資料都是物件,可以設計自己的物件類別(class)。 本文將介紹如何設計class。



Class

先簡單來看一下一個class的結構。

class A:
    def __init__(self, foo, bar):
        self.foo = foo
        self.bar = bar
    
    def show(self):
        print("foo: {0}, bar: {1}".format(self.foo, self.bar))

跟其他許多程式語言相似,使用class關鍵字來宣告物件類別。後面接的是物件類別名稱A。

__init__這個函數是屬於結構函數 constuctor,當類別生成時首先執行的函數。

self為一個預設的參數,所有的函數的第一個參數都是self,代表著物件本身,可以透過它來取得物件的變數與函數。 例如show函數中就是用self來取得物件的變數foo, bar。



實例變數(instance variable) VS 類別變數(class variable)

實例中各自擁有的變數為實例變數,類別中共用的變數為類別變數。

實例變數(instance variable)

實例變數為各個實例中裡所存在的變數。
各個實例間並不共用這些變數,也就表示變數值隨著實例不同而不一樣。
透過self設置的變數都是實例變數。

實例變數的取得

self.foo

實例變數的設定

self.foo = "123"

類別變數(class variable)

同一類別中共用的變數。因此,一經改變則會影響所有相同類別的資料。 類似Java中的static變數。

下面一個簡單的例子,v1與v2就是屬於類別變數。

class A:
    v1 = 1
    v2 = 2

類別變數的取得

A.v1

類別變數的設定

A.v1 = "123"

實例變數與類別變數同時用會如何?

若是實例變數名稱與類別變數名稱都一樣時,取得或設定的會是哪一個呢? 這時候的判斷優先序為 實例變數 > 類別變數。 也就是說會以 實例變數 為主。

一個簡單的例子

class A:
    v1 = 1
    v2 = 2

    def __init__(self, p1):
        self.v1 = p1

    def show(self):
        print(f"show v1: {self.v1}")

a1 = A(3)
print(f"A.v1: {A.v1}") # output: A.v1: 1 類別變數
print(f"A.v2: {A.v2}") # output: A.v2: 2 類別變數
print(f"v1: {a1.v1}")  # output: v1: 3 實例變數
print(f"v2: {a1.v2}")  # output: v2: 2 類別變數
a1.show()              # output: show v1: 3 實例變數

a2 = A(4)
A.v2 = 'v2'
print(f"a.v2: {a1.v2}") # output: a.v1: v2 類別變數
print(f"b.v2: {a2.v2}") # output: b.v1: v2 類別變數


private vs public

若是變數或是函數名稱前面沒有__(兩個下底線_)點綴的話就是public。 若是有__(兩個下底線_)點綴的話就是private。



繼承

繼承也是物件導向一個重要的特色。 以下為一個簡單的B繼承A的例子。

class A:
    def __init__(self):
        self.value = "A"
    def show(self):
        print(f"value: {self.value}")
        
class B(A):

    def output(self):
        print("I am B")

類別名稱後面用(繼承類別名...)的形式來宣告繼承,括號內中可以宣告多個類別達成 多重繼承 的目的。

多重繼承時若是有重複的函數名或變數名稱時,以括號內的宣告順序為主。先宣告的優先度最高。



const

Python中似乎沒有類似const這樣的關鍵字來宣告常數。
若是有需要的話,可以設計一個常數的類別(class)將常數定義於其中來使用。
或是使用他人開發的模組來使用。