工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> Python

Python @propertyデコレータマスター:クリーンで後方互換なゲッター/セッター

Python @propertyデコレータマスター

Pythonの組み込み@propertyデコレータが如何に簡潔で保守しやすいゲッター/セッターを書きながらAPIの後方互換性を保つかを学びます。

Pythonの@propertyデコレータは属性アクセスのカプセル化に強力なツールです。属性読み書き時にカスタムロジックを実行させつつ、呼び出し側コード変更を強制しません。以下では実例—温度変換処理—を通じて制約強制方法を示し、なぜ@propertyがイディオマチックな解決策かを説明します。

ゲッター/セッターなしのクラス

摂氏で温度を格納し、華氏変換可能なシンプルなクラスが必要とします:

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

使用は簡単:

# 新オブジェクト作成
human = Celsius()
# 温度設定
human.temperature = 37
# 温度読み取り
print(human.temperature)
# 華氏変換
print(human.to_fahrenheit())

出力

37 98.60000000000001

浮動小数点結果はバイナリでの10進表現によるもの。human.__dict__を見ると、Pythonが値を普通の辞書エントリとして格納しているのがわかります:

>>> human.__dict__
{'temperature': 37}

ゲッター/セッターで制約追加

実世界オブジェクトは検証を必要とすることが多々あります。例えば温度は絶対零度(-273.15 °C)未満になりえません。単純な方法は属性を隠蔽し、明示的ゲッター/セッターメソッドを公開すること:

class Celsius:
    def __init__(self, temperature=0):
        self.set_temperature(temperature)
    def to_fahrenheit(self):
        return (self.get_temperature() * 1.8) + 32
    # ゲッター
    def get_temperature(self):
        return self._temperature
    # セッター
    def set_temperature(self, value):
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible.")
        self._temperature = value

これでクラスは下限を強制しますが、obj.temperatureでアクセスしていた既存コードはobj.get_temperature()とobj.set_temperature(val)呼び出しに書き換え必須。大規模コードベースでは大規模リファクタリングになります。

さらに、Pythonの「プライベート」変数は命名規約に過ぎず—_temperatureにも直接アクセス可能でカプセル化が破れます。ここで@propertyが真価を発揮します。

propertyクラスの使用

Pythonはゲッター/セッター関数を属性名に結びつけるpropertyクラスを提供:

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    # ゲッター
    def get_temperature(self):
        print("Getting value...")
        return self._temperature
    # セッター
    def set_temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273.15 is not possible")
        self._temperature = value
    # プロパティとして公開
    temperature = property(get_temperature, set_temperature)

このセットアップでは、以下のコードが元のシンプルクラスと全く同じように振る舞いますが、裏で検証が働きます:

human = Celsius(37)
print(human.temperature)  # ゲッター発火
print(human.to_fahrenheit())  # 内部でゲッター使用
human.temperature = -300  # セッター発火、ValueError発生

出力

Setting value... Getting value... 37 Getting value... 98.60000000000001 Setting value... Traceback (most recent call last): ... ValueError: Temperature below -273 is not possible

temperatureアクセスコードは変更不要;実装のみが検証を獲得しました。

ヒント:実際のデータは_temperatureに格納;temperatureは便利で安全なインターフェースに過ぎません。

@propertyデコレータ

propertyクラスでも動作しますが、Pythonのデコレータ構文ならよりクリーンで可読な同等結果が得られます。デコレータが自動的にプロパティオブジェクトを作成し、ゲッター/セッターを属性名に結びつけます。

class Celsius:
    def __init__(self, temperature=0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    @property
    def temperature(self):
        print("Getting value...")
        return self._temperature
    @temperature.setter
    def temperature(self, value):
        print("Setting value...")
        if value < -273.15:
            raise ValueError("Temperature below -273 is not possible")
        self._temperature = value

使用方法は同じ:

human = Celsius(37)
print(human.temperature)
print(human.to_fahrenheit())
# 無効温度設定試行
try:
    Celsius(-300)
except ValueError as e:
    print(e)

出力

Setting value... Getting value... 37 Getting value... 98.60000000000001 Setting value... Traceback (most recent call last): ... ValueError: Temperature below -273 is not possible

@property使用で名前空間が整理され、別個のゲッター/セッターメソッド名が不要になり、ほとんどのPython開発者に推奨されるパターンです。

Python

  1. Python データ型マスター: 実践ガイド
  2. Python 演算子完全マスター: 包括的ガイド
  3. Python pass文完全マスター: 実践ガイド
  4. Python 関数引数完全マスター: 位置引数・キーワード引数・デフォルト引数
  5. Python辞書完全ガイド:作成、操作、高度なテクニック
  6. Python継承マスター:概念、構文、実践例
  7. Python演算子オーバーロード完全ガイド:__add__、__lt__など特殊メソッドでOOP設計を強化
  8. Pythonイテレータ完全ガイド:仕組みと自作方法
  9. Pythonクロージャ解説:ネスト関数が変数を捕捉する仕組み
  10. Python @propertyデコレータマスター:クリーンで後方互換なゲッター/セッター
  11. Python datetimeマスター:日付・時刻・タイムゾーン実践ガイド