fbpx

本篇接續淺談Python類別(Class)文章,細談Python類別(Class)中的屬性(Attribute)觀念。我們知道屬性(Attribute)可以分為實體屬性(Instance Attribute)與類別屬性(Class Attribute),今天就來探討它們的用法以及不一樣的地方。另外,也會介紹Python屬性(Property)的應用方式。

  • 實體屬性(Instance Attribute)
  • 類別屬性(Class Attribute)
  • 屬性(Property)

一、實體屬性(Instance Attribute)

需伴隨物件(Object)的生成來建立,也就是透過點(.)的語法或在建構式(Constructor)中所生成的屬性(Attribute)。各物件(Object)的實體屬性(Instance Attribute)各自獨立,修改某一個物件(Object)的實體屬性(Instance Attribute)值時,不會影響到其他物件。如下範例:

執行結果


從範例中可以看到,我們透過點(.)的方式來建立物件(Object)的屬性(Attribute)mazdatoyota物件的colorseat為實體屬性(Instance Attribute),互相獨立且有各自的屬性值。接下來我們來看透過建構式(Constructor)所建立的屬性(Attribute)

執行結果


在第12~14行我們修改了mazda物件(Object)colorseatweight屬性(Attribute)值,並不會影響到其他物件toyota的屬性值,所以我們可以說colorseatweight為實體屬性(Instance Attribute)

二、類別屬性(Class Attribute)

定義在類別層級的屬性(Attribute),也就是在建構式(Constructor)之外的屬性(Attribute)。可以不需要建立物件(Object),直接透過類別名稱存取。各物件共享類別屬性(Class Attribute)值,也就是說當我們修改類別屬性(Class Attribute)值時,每一個透過此類別(Class)所建立的物件(Object),都會受到影響。如下範例:

執行結果


我們可以看到door屬性(Attribute)定義在建構式(Constructor)之外,所以為類別屬性(Class Attribute),並且在第18行透過類別名稱來修改其屬性值,之後所有物件(Object)如mazda及toyota物件(Object)的door屬性值皆改變了。

三、屬性(Property)

是一個允許我們設定及取得屬性(Attribute)值的物件(Object),當我們想要對類別(Class)中的屬性(Attribute)有更多的控制時,就會使用Python的屬性(Property)來達成。先來看一個範例:

我們初始化屬性(Attribute)時,傳入車重屬性值為-200,Python編譯器不會報任何錯誤,但是實際上車重不可能為負的,這時候我們要怎麼防止來源端傳入不正確的資料,而間接影響程式邏輯?有寫過其他物件導向程式語言的開發人員可能會這樣做:

 

執行結果


範例於建構式(Constructor)中,呼叫設定屬性(Attribute)的方法(Method)來設定其值,並於方法(Method)中判斷如果傳入值小於等於0時,丟出例外錯誤,否則就設定weight屬性(Attribute)值。由於我們傳入了負數,所以從執行結果可以看到ValueError的例外錯誤。

雖然此方法可以達到檢核的目的,但是這樣的寫法不”Pythonic”,意思是沒有寫出Python的特點或風格,我們可以使用Python的屬性(Property)來達到相同的效果。如下範例:

在讀取屬性(Attribute)的方法(原get_weight()方法)上方加上@property Decorator,並且將方法名稱修改為weight,這個weight就是屬性(Property)。接著在設定屬性(Attribute)的方法(原set_weight()方法)上方加上@property.setter,也就是@weight.setter,意思就是告訴類別(Class)當來源端要設定屬性(Property)值時,要呼叫這個方法(Method)。同樣我們將方法名稱修改為weight,最後別忘了修改建構式(Constructor)中的屬性(Property)設定。

對來源端來說,設定或讀取的屬性(Attribute),事實上在類別(Class)中,是呼叫了屬性(Property)的設定方法(setter)及讀取方法(getter)。

我們來測試一下修改後的結果:

設定mazda物件(Object)的車重屬性(Property)為100時,建構式(Constructor)呼叫加了@weight.setter的設定屬性(Property)方法(Method),而第3行在存取物件(Object)的屬性(Property)時,則是呼叫加了@property的讀取屬性(Property)方法(Method)。

另外我們傳入負數,同樣會得到ValueError的例外錯誤訊息,如下範例:

執行結果

四、小結

以上就是針對Python屬性的詳細介紹,希望透過此文章,可以有更進一步的認識,在練習的過程中若有碰到任何問題或說明不清楚的地方,歡迎留言與我分享!

「好文轉自古耕全–3個必須瞭解的Python屬性觀念如果你喜歡他的文章歡迎回到他的部落格看更多:)」