Pythonでプロパティを定義する場合、propertyクラスとpropertyデコレータを使用する方法があります。
property関数
第一引数でgetterのみ指定しているため、setterはありません。つまり読み取り専用のプロパティであるためurlを更新しようとするとエラーになります。
class PropertyTest(object): def __init__(self, url): self._url = url def get_url(self): print('-- get_url --') return self._url url = property(get_url) prop = PropertyTest('https://www.python-izm.com/') # プロパティ「url」を取得 print(prop.url) # getterのみの定義なので更新しようとするとエラー # prop.url = 'python-izm'
-- get_url -- https://www.python-izm.com/
propertyクラスにはgetter、setter、deleter、ドキュメント文字列を渡すことができます。下記の例ではsetterを定義しているため、プロパティを更新することができます。
class PropertyTest(object): def __init__(self, url): self._url = url def get_url(self): print('-- get_url --') return self._url def set_url(self, url): print('-- set_url --') self._url = url def del_url(self): del self._url url = property(get_url, set_url, del_url, 'url Property') prop = PropertyTest('https://www.python-izm.com/') # setter(set_url)にアクセス prop.url = 'python-izm' # getter(get_url)にアクセス print(prop.url)
-- set_url -- -- get_url -- python-izm
getter内で他の属性を参照しても構いません。次の例はschemaとhostからurl文字列を返しています。
class PropertyTest(object): def __init__(self, scheme, host): self.schema = scheme self.host = host def get_url(self): return('{}://{}/'.format(self.schema, self.host)) url = property(get_url) prop = PropertyTest('https', 'www.python-izm.com') print(prop.url)
https://www.python-izm.com/
propertyデコレータ
メソッドへ@propertyを付与するとそのメソッドはgetterになります。setterは定義していないので、読み取り専用のプロパティです。urlを更新しようとするとエラーになります。
class PropertyTest(object): def __init__(self, url): self._url = url @property def url(self): print('-- get_url --') return self._url prop = PropertyTest('https://www.python-izm.com/') # プロパティ「url」を取得 print(prop.url) # getterのみの定義なので更新しようとするとエラー # prop.url = 'python-izm'
-- get_url -- https://www.python-izm.com/
次のような形でgetter、setter、deleterを定義することができます。この例ではsetterを定義しているため、プロパティを更新することができます。
class PropertyTest(object): def __init__(self, url): self._url = url @property def url(self): print('-- get_url --') return self._url @url.setter def url(self, url): print('-- set_url --') self._url = url @url.deleter def url(self): del self._url prop = PropertyTest('https://www.python-izm.com/') # setterにアクセス prop.url = 'python-izm' # getterにアクセス print(prop.url)
-- set_url -- -- get_url -- python-izm
getter内で他の属性を参照しても構いません。次の例はschemaとhostからurl文字列を返しています。
class PropertyTest(object): def __init__(self, scheme, host): self.schema = scheme self.host = host @property def url(self): return('{}://{}/'.format(self.schema, self.host)) prop = PropertyTest('https', 'www.python-izm.com') print(prop.url)
https://www.python-izm.com/
旧クラススタイルでは
旧スタイルのクラスでプロパティを定義すると、特に問題なく動作しているように見えます。ただし下記例のようにgetterしか定義していない読み取り専用のプロパティであるにも関わらずurlが更新できてしまいます。プロパティを定義する時は新スタイルでクラスを作成しましょう。
※旧クラススタイル、新クラススタイルの詳細は新旧クラススタイルを参照してください。
class PropertyTest: def __init__(self, url): self._url = url @property def url(self): print('-- get_url --') return self._url prop = PropertyTest('https://www.python-izm.com/') print(prop.url) prop.url = 'python-izm' print(prop.url)
-- get_url -- https://www.python-izm.com/ python-izm