あるクラスの設計で、何かの計算された値を返したいとき、引数なしのメソッドを実装することが有ると思います。
その場合、値の取得は次のような形になります。
しかし、返される値が何かの属性値、例えばそのオブジェクトの長さのようなものであれば、括弧なしで x.foo
として取得したくなるのが人情というものです。
@property デコレータ
Python 3 には、そのような動作を手軽な記述で可能にする @property
デコレータがあります。
次の例で、@property
デコレータの基本的な利用法を示します。
なお、@wrapper 構文のデコレータは、メソッド(関数)やクラスの直前の行に付与することで、その定義内容を自動的に書き換える為の仕組みです。
文字数を返す属性値の実装
Python 3 の文字列クラス str
には、JavaScript 等のように length プロパティは無く、組み込み関数 len(s)
で文字列 s の長さを取得します。
そこで、文字数を s.length
でも取得できるように実装してみましょう。
class String(str):
""" JavaScript の String.length 相当の属性を持つ文字列 """
@property
def length(self):
""" 文字数の取得 """
return len(self)
s = String('foobar')
print(s, type(s))
# foobar <class '__main__.String'>
print(s.length)
# 6
クラス str
を継承し、length プロパティを実装した新たな文字列クラス String を作りました。
length メソッド内の定義方法は通常のメソッドと同様ですが、@property
の付与により s.length
で戻り値が取得できるようになっています。
メソッドが読み出し専用属性になる
上記の例の length は読み出し専用属性に変化しており、値を書き込んだり、s.length()
として実行することは出来ません。
s.length = 2
# AttributeError: can't set attribute
s.length()
# TypeError: 'int' object is not callable
従って、単に読み出し専用属性を作りたい時にも @property
は便利と言えます。
また、読み出し専用を含むデータ用クラスを作りたい時は、@dataclass
デコレータも便利です。
※ Python 3.7 で動作確認しました。
参考サイト
- 組み込み関数 — Python 3 ドキュメント : class property の説明
- dataclasses — データクラス — Python 3 ドキュメント
- 用語集 — Python 3 ドキュメント : デコレータ等の用語解説
コメントを投稿