0
0

More than 3 years have passed since last update.

Python プロパティの良さを探す。

Last updated at Posted at 2020-07-26

pythonのプロパティに関しての記事です。

__slots__やコメント、型ヒントなどは省略しています。

あまり恩恵がわかりにくい例

1.インスタンス変数のみ

class Data:

    def __init__(self):
        self.x = "a"

2.プロパティで書いたパターン

class Data:

    def __init__(self):
        self._x = "a"

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, arg_x):
        self._x = arg_x

✴︎1 アンダースコア()は直接アクセスして欲しくない変数につけます。
より強固にする場合はアンダースコアを二つにする(
_)

上記のクラスをどちらを使っても同じ結果になります

data = Data()
print(data.x)
data.x = "b"
print(data.x)

>>a
>>b

この二つの例だけでは恩恵がわかりにくいですが、いくつかのポイントに注目しておくと良いです。

 1.プロパティでは直接値を保持するインスタンス変数をプロパティを介していじっている事
 2.プロパティでは値を取得するまたはセットする場合に処理(確認)する構造を持たせやすいこと。

例1 自身が保持する値(設定)が、他の値に依存するパターン

まずはインスタンス変数のみでクラスを用意してみました。

class Lock:
    """
    錠クラス
    """
    def __init__(self):
        self.word = ""
        self.number = 0

        self.input_state = {
                            "word": self.word,
                            "number": self.number
                            }
lock1 = Lock()
lock1.word = "a"
print(lock1.input_state)
>> {'word': '', 'number': 0}

wordに"a"を入れたのに、input_stateの"word"の値は変化していませんよね。
これはinput_stateは初期化時に値が決まってしまうため、"word"の値は更新されません。
(初期入力時だけ覚えこませる変数としてならありかも知れません。)

class Lock:
    """
    錠クラス

    """
    def __init__(self):
        # 暗証番号
        self.word = ""
        self.number = 0

    @property
    def input_state(self):
        return {
                "word": self.word,
                "number": self.number
                }
lock1 = Lock()
lock1.word = "a"
print(lock1.input_state)
>> {'word': 'a', 'number': 0}

今度はwordが変更された時にinput_stateは更新されていますね。

例2 バリデイトしたい場合

今度はwordに"b"を入れるのは禁止にしたい場合を考えます。

class InvalidWordError(Exception):
    pass


class Lock:
    """
    錠クラス

    """
    def __init__(self):
        # 暗証番号
        self._word = ""
        self.number = 0

    @property
    def word(self):
        return self._word

    @word.setter
    def word(self, arg):

        if arg == "b":
            raise InvalidWordError()

        self._word = arg

    @property
    def input_state(self):
        return {
                "word": self.word,
                "number": self.number
                }

aを入力する場合

lock1 = Lock()
lock1.word = "a"
print(lock1.input_state)

>> {'word': 'a', 'number': 0}

bを入力する場合

lock1 = Lock()
lock1.word = "b"
print(lock1.input_state)

>Traceback (most recent call last):
>  File "〇〇.py", line 39, in <module>
>    lock1.word = "b"
>  File "〇〇.py", line 23, in word
>    raise InvalidWordError()
>〇〇.InvalidWordError

今回は無効な文字("b")が入った場合に例外を出す様にしています。

他の開発者がクラスを扱いやすくするための工夫は大事ですね。
またプロパティはカプセル化にも通じる話だと思うのでオブジェクト思考では欠かせない存在。。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0