Photo by Jeff Sheldon on Unsplash
本篇接續淺談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)值時,不會影響到其他物件。如下範例:
# 汽車類別
class Cars:
pass
mazda = Cars()
mazda.color = "blue"
mazda.seat = 4
toyota = Cars()
toyota.color = "red"
toyota.seat = 6
print("mazda color: ", mazda.color)
print("mazda seat: ", mazda.seat)
print("toyota color: ", toyota.color)
print("toyota seat: ", toyota.seat)
執行結果
# 汽車類別
class Cars:
# 建構式
def __init__(self, color, seat):
self.color = color
self.seat = seat
self.weight = 140
mazda = Cars("blue", 4)
mazda.color = "yellow"
mazda.seat = 8
mazda.weight = 200
toyota = Cars("red", 6)
print("mazda color: ", mazda.color)
print("mazda seat: ", mazda.seat)
print("mazda weight: ", mazda.weight)
print("toyota color: ", toyota.color)
print("toyota seat: ", toyota.seat)
print("toyota weight: ", toyota.weight)
執行結果二、類別屬性(Class Attribute)
定義在類別層級的屬性(Attribute),也就是在建構式(Constructor)之外的屬性(Attribute)。可以不需要建立物件(Object),直接透過類別名稱存取。各物件共享類別屬性(Class Attribute)值,也就是說當我們修改類別屬性(Class Attribute)值時,每一個透過此類別(Class)所建立的物件(Object),都會受到影響。如下範例:
# 汽車類別
class Cars:
door = 4
# 建構式
def __init__(self, color, seat):
self.color = color
self.seat = seat
self.weight = 140
mazda = Cars("blue", 4)
toyota = Cars("red", 6)
print("mazda original door: ", mazda.door) # door原值
print("toyota original door: ", toyota.door) # door原值
Cars.door = 6
print("mazda new door: ", mazda.door) # door新值
print("toyota new door: ", toyota.door) # door新值
執行結果
三、屬性(Property)
# 汽車類別
class Cars:
# 建構式
def __init__(self, weight):
self.weight = weight #車重屬性
mazda = Cars(-200)
我們初始化屬性(Attribute)時,傳入車重屬性值為-200,Python編譯器不會報任何錯誤,但是實際上車重不可能為負的,這時候我們要怎麼防止來源端傳入不正確的資料,而間接影響程式邏輯?有寫過其他物件導向程式語言的開發人員可能會這樣做:
# 汽車類別
class Cars:
# 建構式
def __init__(self, weight):
self.set_weight(weight)
def get_weight(self):
return self.__weight
def set_weight(self, value):
if value <= 0:
raise ValueError("Car weight cannot be 0 or less.")
self.__weight = value
mazda = Cars(-200)
執行結果雖然此方法可以達到檢核的目的,但是這樣的寫法不"Pythonic",意思是沒有寫出Python的特點或風格,我們可以使用Python的屬性(Property)來達到相同的效果。如下範例:
# 汽車類別
class Cars:
# 建構式
def __init__(self, weight):
self.weight = weight
@property
def weight(self):
return self.__weight
@weight.setter
def weight(self, value):
if value <= 0:
raise ValueError("Car weight cannot be 0 or less.")
self.__weight = value
在讀取屬性(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 = Cars(100)
print(mazda.weight)
設定mazda物件(Object)的車重屬性(Property)為100時,建構式(Constructor)呼叫加了@weight.setter的設定屬性(Property)方法(Method),而第3行在存取物件(Object)的屬性(Property)時,則是呼叫加了@property的讀取屬性(Property)方法(Method)。另外我們傳入負數,同樣會得到ValueError的例外錯誤訊息,如下範例:
mazda = Cars(-200)
執行結果四、小結
以上就是針對Python屬性的詳細介紹,希望透過此文章,可以有更進一步的認識,在練習的過程中若有碰到任何問題或說明不清楚的地方,歡迎留言與我分享!如果您喜歡我的文章,請幫我按五下Like(使用Google或Facebook帳號免費註冊),支持我創作教學文章,回饋由LikeCoin基金會出資,完全不會花到錢,感謝大家。
有想要看的教學內容嗎?歡迎利用以下的Google表單讓我知道,將有機會成為教學文章,分享給大家😊
留言
張貼留言