『Effective Python』の続き。@property
大好き一番好きなデコレータです!
www.effectivepython.com
@property
を使えばクラス全体をリファクタリングすることなく属性のリファクタリングができますよ、という話。
リーキーバケット - Wikipedia
をPythonで実装するという題材で説明している。
from datetime import datetime, timedelta class Bucket(object): def __init__(self, period): self.period_delta = timedelta(seconds=period) self.reset_time = datetime.now() self.quota = 0 def __repr__(self): return 'Bucket(quota=%d)' % self.quota
が最初の実装である。
ここに、クォータの最大量と消費量を追加したいという要望があったとする。
勿論、self.quota
を書き換えればよいのだが、既に利用者がself.quota
を使ってしまっている…という状況でも、
class Bucket(object): def __init__(self, period): self.period_delta = timedelta(seconds=period) self.reset_time = datetime.now() self.max_quota = 0 self.quota_consumed = 0 def __repr__(self): return ('Bucket(max_quota=%d, quota_consumed=%d)' % (self.max_quota, self.quota_consumed)) @property def quota(self): return self.max_quota - self.quota_consumed @quota.setter def quota(self, amount): delta = self.max_quota - amount if amount == 0: # Quota being reset for a new period self.quota_consumed = 0 self.max_quota = 0 elif delta < 0: # Quota being filled for the new period assert self.quota_consumed == 0 self.max_quota = amount else: # Quota being consumed during the period assert self.max_quota >= self.quota_consumed self.quota_consumed += delta
とすれば、内部でself.quota
が「現在量」「最大量から消費量を差し引く」と実装が変わっていても、
クラスの利用者はself.quota
を「現在量」としてそのまま扱うことが出来る、という流れである。
なお、筆者は@property
が好きなようである。
I especially like
@property
because...
とあるぐらい。
なお、次回も@property
の例である。