iT邦幫忙

0

Python 裝飾器 (decorator): @property 與 @setter

  • 分享至 

  • xImage
  •  

@property 和 @setter 是 Python 中的 裝飾器 (decorators),
用來實現對物件屬性的更方便且受控的訪問與修改。
它們經常搭配使用,可以讓類別中的方法表現得像屬性一樣(使用點語法,而不是方法調用)。

  1. @property
    把一個方法轉換成一個唯讀屬性。
    使方法能夠像屬性一樣被訪問,並且可以在方法內添加邏輯,控制屬性值的計算或取得。
    語法
class MyClass:
    @property
    def my_attribute(self):
        # 返回計算或取得的值
        return some_value
class Circle:
    def __init__(self, radius):
        self._radius = radius  # 私有屬性,外部不直接訪問

    @property
    def radius(self):
        # 允許通過 .radius 獲取半徑
        return self._radius

    @property
    def area(self):
        # 允許通過 .area 獲取計算的面積
        return 3.14159 * (self._radius ** 2)

circle = Circle(5)
print(circle.radius)  # 5
print(circle.area)    # 78.53975
  1. @<property_name>.setter
  • @property 和 @property.setter 是配套使用的裝飾器,允許為屬性提供讀取和寫入的功能。
  • 定義對屬性的修改方法,讓屬性可以被設置,並在設置時執行額外的邏輯或驗證。
    語法
class MyClass:
    @property
    def my_attribute(self):
        return self._value

    @my_attribute.setter
    def my_attribute(self, value):
        # 自定義邏輯來設置屬性值
        self._value = value

範例

class Circle:
    def __init__(self, radius):
        self._radius = radius  # 私有屬性

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        if value <= 0:
            raise ValueError("半徑必須大於 0")
        self._radius = value

circle = Circle(5)
print(circle.radius)  # 5

circle.radius = 10     # 修改半徑
print(circle.radius)  # 10

# circle.radius = -3  # 會拋出 ValueError: 半徑必須大於 0
  1. 為什麼使用 @property 和 @setter?
    優點
    3-1 封裝性
    • 屬性可以設為私有,外部只能通過 @property 和 @setter 訪問,保持物件內部邏輯的完整性。
    • 在需要時加入檢查邏輯,而無需修改外部調用程式碼。
      3-2 易於理解的 API
  • 使用點語法訪問屬性,符合直覺,讓物件更易於使用。
    3-3 靈活性
  • 可以根據需要調整屬性值的邏輯,而不影響外部程式碼。
  1. @property 和 @setter 的完整範例
class Rectangle:
    def __init__(self, width, height):
        self._width = width
        self._height = height

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        if value <= 0:
            raise ValueError("寬度必須大於 0")
        self._width = value

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self, value):
        if value <= 0:
            raise ValueError("高度必須大於 0")
        self._height = value

    @property
    def area(self):
        # 面積是只讀屬性,無法直接修改
        return self._width * self._height

使用範例

rect = Rectangle(4, 5)
print(rect.width)   # 4
print(rect.height)  # 5
print(rect.area)    # 20

rect.width = 10
rect.height = 2
print(rect.area)    # 20 -> 10*2 = 20

# rect.area = 50  # AttributeError: can't set attribute

總結

@property 將方法變成屬性,可以用來封裝屬性邏輯。
@setter 定義屬性的設置邏輯,對屬性修改進行控制和檢查。
它們提高了物件的封裝性和可用性,同時保留靈活性,是 Python 中強大的特性之一。

Python 的裝飾器(Decorator)目錄
其他Python 的裝飾器(Decorator文章:
Python 裝飾器 (decorator): @classmethod
Python 裝飾器 (decorator): @staticmethod
Python 裝飾器 (decorator) @abstractmethod


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言