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
