Last Updated on 2024-08-27 by Clay
在 Python 的類別建構中,@property
是一種經常見到且確實有其好處的裝飾器,它主要的用途在於將類別的方法(class method)轉為只讀(read-only)的屬性(attribute),讓使用者透過屬性呼叫的方式來取得計算結果。
另一個優點則是可以使程式碼在閱讀或維護時更加直觀,可以隱去一些計算細節。
使用方式
以下我們來看一個轉換時間戳(timestamp)為日期字串的類別,其中每個類別方法都返回不同格式的日期;只要我們修改了類別的時間戳,就可以在呼叫對應的 @property 類別方法時,看到被轉換好的結果。(而且使用方式跟類別屬性一樣)
import datetime
class TimestampFormatter:
def __init__(self, timestamp):
self._timestamp = timestamp
@property
def date_slash(self):
""" Return format yyyy/mm/dd """
date = datetime.datetime.fromtimestamp(self._timestamp)
return date.strftime('%Y/%m/%d')
@property
def date_dash(self):
""" Return format yyyy-mm-dd """
date = datetime.datetime.fromtimestamp(self._timestamp)
return date.strftime('%Y-%m-%d')
@property
def date_dot(self):
""" Return format yyyy.mm.dd """
date = datetime.datetime.fromtimestamp(self._timestamp)
return date.strftime('%Y.%m.%d')
@property
def date_space(self):
""" Return format yyyy mm dd """
date = datetime.datetime.fromtimestamp(self._timestamp)
return date.strftime('%Y %m %d')
if __name__ == "__main__":
current_timestamp = datetime.datetime.now().timestamp()
# Create TimestampFormatter instance
formatter = TimestampFormatter(int(current_timestamp))
# Print different format
print("Date with slashes:", formatter.date_slash)
print("Date with dashes:", formatter.date_dash)
print("Date with dots:", formatter.date_dot)
print("Date with spaces:", formatter.date_space)
Output:
Date with slashes: 2024/08/27
Date with dashes: 2024-08-27
Date with dots: 2024.08.27
Date with spaces: 2024 08 27
直覺上,這樣有點類似我們設置好類別實體的一個屬性值,其他屬性值也會與之相對改變,在類別不同屬性之間彼此有關聯的情況下這樣寫特別直覺。
擴展使用
Setter 方法
setter
方法是 @property
裝飾器的一個使用方法,用於設置或修改屬性的值。當我們需要在替類別的屬性賦值時進行額外的檢查或轉換,例如數據驗證或自動格式化,setter
方法是一個理想的選擇。
基本用法
我們可以透過在方法名前加上 @<property_name>.setter
來定義 setter(我一開始其實看不懂 <property_name>
的命名是哪裡來的,後來才發現是我們自己定義的方法),以下是一個範例:
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, value):
if not isinstance(value, str):
raise TypeError("Name must be a string")
self._name = value
在這個例子中,當嘗試設置 name
屬性時,setter
方法會先檢查新值是否為字符串。如果不是,將拋出一個 TypeError
。
Deleter 方法
deleter
方法用於定義當一個屬性被刪除時需要進行的操作,例如清理或釋放資源。這在處理文件或數據庫連接時尤為重要。
基本用法
deleter
可以通過在方法名前加上 @<property_name>.deleter
來定義。以下是一個範例:
class Person:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.deleter
def name(self):
print("Deleting name...")
del self._name
當 del
操作被用於 name
屬性時,會調用這個 deleter
方法,進行額外的日誌記錄或其他清理操作。
總結來說,使用 @property
有著以下好處:
- 異常處理:在
setter
和deleter
方法中添加異常處理,可以防止不正確的使用方式對物件造成損害 - 依賴屬性:當某個屬性的值取決於其他屬性時,可以使用
@property
來確保所有相關屬性都是同步更新的 - 暫存計算值:對於計算成本高的屬性,可以在第一次計算後將結果暫存起來,後續訪問直接返回緩存值,直到相依的資料發生變化
References
- Built-in Functions — Python 3.12.5 documentation
- Stack Overflow – How to document fields and properties in Python?