プロパティ | Python-izm

プロパティ

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内で他の属性を参照しても構いません。次の例はschemahostから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内で他の属性を参照しても構いません。次の例はschemahostから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