Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Python辞典

  1. トップページ
  2. Python辞典
  3. @property / @classmethod / @staticmethod

@property / @classmethod / @staticmethod

『@property』はメソッドをプロパティとして使えるようにするデコレータで、クラスの属性へのアクセスに処理を追加できます。『@classmethod』はインスタンスではなくクラス自体を第一引数(cls)として受け取るメソッドを定義し、『@staticmethod』はクラスやインスタンスに依存しない汎用的な処理を定義します。

構文
class MyClass:
    # プロパティ(読み取り)
    @property
    def 属性名(self):
        return self._属性名

    # プロパティ(書き込み)
    @属性名.setter
    def 属性名(self, value):
        self._属性名 = value

    # クラスメソッド(cls = クラス自体)
    @classmethod
    def クラスメソッド(cls, 引数):
        ...

    # 静的メソッド(self も cls も不要)
    @staticmethod
    def 静的メソッド(引数):
        ...
デコレータ一覧
デコレータ概要
@propertyメソッドをプロパティ(読み取り専用アクセス)として定義する。
@属性名.setterプロパティへの代入時に実行するメソッドを定義する。
@属性名.deleterプロパティをdel文で削除するときに実行するメソッドを定義する。
@classmethod第一引数にクラス自体(cls)を受け取るメソッドを定義する。
@staticmethodselfもclsも受け取らない静的メソッドを定義する。
サンプルコード
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius

    @property
    def celsius(self):
        """摂氏温度を返す"""
        return self._celsius

    @celsius.setter
    def celsius(self, value):
        if value < -273.15:
            raise ValueError("絶対零度以下には設定できません")
        self._celsius = value

    @property
    def fahrenheit(self):
        """華氏温度を計算して返す(読み取り専用)"""
        return self._celsius * 9 / 5 + 32

# プロパティを使ったアクセス(メソッド呼び出し不要)
t = Temperature(100)
print(t.celsius)        # 100
print(t.fahrenheit)     # 212.0

t.celsius = 0           # setterが実行される
print(t.fahrenheit)     # 32.0

try:
    t.celsius = -300    # バリデーションエラー
except ValueError as e:
    print(e)


class User:
    _count = 0

    def __init__(self, name, email):
        self.name  = name
        self.email = email
        User._count += 1

    @classmethod
    def get_count(cls):
        """生成されたインスタンス数を返す"""
        return cls._count

    @classmethod
    def from_dict(cls, data):
        """辞書からインスタンスを生成するファクトリメソッド"""
        return cls(data['name'], data['email'])

    @staticmethod
    def is_valid_email(email):
        """メールアドレスの簡易バリデーション(クラスに依存しない処理)"""
        return '@' in email and '.' in email

# クラスメソッドの使用
u1 = User('田中', 'tanaka@example.com')
u2 = User.from_dict({'name': '鈴木', 'email': 'suzuki@example.com'})
print(User.get_count())     # 2

# 静的メソッドの使用(インスタンス不要)
print(User.is_valid_email('test@example.com'))  # True
print(User.is_valid_email('invalid'))           # False
概要

『@property』を使うと、インスタンス変数へのアクセスに自動的にバリデーションや変換処理を追加できます。クラスの内部実装を変更しても、外部からはプロパティとして同じ形式でアクセスできるため、APIの互換性を保ちやすくなります。

『@classmethod』は代替コンストラクタ(ファクトリメソッド)として頻繁に使われます。例えばJSONや辞書からインスタンスを生成するfrom_dict()メソッドを定義するパターンが一般的です。

『@staticmethod』はクラスに論理的に属するが、クラスやインスタンスの状態を使わない処理に使います。selfもclsも使わない処理はstaticmethodにすることで、クラスの外でなくクラスのスコープに置くべき処理であることを明示できます

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。