クラスの中で@propertyのデコレータを使うと、
属性として取り出すことが可能になります。
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
@property
def x(self):
return self._x
@property
def y(self):
return self._y
@property
def sum(self):
return self._x + self._y
point = Point(10, 20)
print(point.x, point.y, point.sum)
# 10 20 30
この状態で再代入しようとしてもエラーが出てしまいます。
xを15に置き換えようとします。
point.x = 15
すると下記のエラーがでます。
setterの設定
再代入でエラー表示させないためにsetterを設定していきます。
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self._y = value
@property
def sum(self):
return self._x + self._y
point = Point(10, 20)
print(point.x, point.y, point.sum)
# 10 20 30
このように各プロパティでsetterを用意すると再代入が可能になります。
point.x = 15
print(point.x, point.y, point.sum)
# 15 20 35
setterの設定を限定させる
例えば、0より大きい値しか入れさせたくない場合は
下記のようにsetterを書いてあげます。
@x.setter
def x(self, value):
if value <= 0:
raise ValueError(f'xは0より大きい値にしてください。入力値:{value}')
self._x = value
全体のコードは下記になります。
class Point:
def __init__(self, x, y):
self._x = x
self._y = y
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if value <= 0:
raise ValueError(f'xは0より大きい値にしてください。入力値:{value}')
self._x = value
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self._y = value
@property
def sum(self):
return self._x + self._y
ただし、この方法だとインスタンス時にエラーが表示されません。
point = Point(-10, 20) # 負の値を入れてもエラーにならない
print(point.x, point.y, point.sum)
インスタンス時にsetterを動かして入力制限をする方法を次に記載します。
インスタンス化時点で引数の制限を実装する方法
親クラスを作成して継承させるとインスタンス時の引数も判定してくれます。
class Meta:
def __init__(self, x, y):
self.x = x
self.y = y
class Point(Meta):
def __init__(self, x, y):
super().__init__(x, y)
@property
def x(self):
return self._x
@x.setter
def x(self, value):
if value <= 0:
raise ValueError(f'xは0より大きい値にしてください。入力値:{value}')
self._x = value
@property
def y(self):
return self._y
@y.setter
def y(self, value):
self._y = value
@property
def sum(self):
return self._x + self._y
このように設定した場合、インスタンス時の引数でxに負の値を渡すとエラーが生じます。
# こちらは問題なく動く
point = Point(10, 20)
print(point.x, point.y, point.sum)
# 10 20 30
# 負の値を渡すとエラーになる
point = Point(-10, 20)
# ValueError: xは0より大きい値にしてください。入力値:-10
どのようなときにプロパティの設定をするのか?
これは完全に自分で考えた内容なので、違うかもしれない前提で読んでいただきたいと思います。
プロパティを設定する場合は大きく2つあるかなと思います。
- 参照と変更が簡単に可能になる
- メソッドなどで指定しなくても変更したら自動計算されて出力が可能
2に関しては上記例題のsumの例です。
前提として、プロパティの設定をする際はsetter
と一緒に使わないと意味がないです。
なぜなら@property
を設定しなくてもコンストラクタの内容は
属性として取得可能だからです。
pandasの例だとDataFrame.columns
がわかりやすいと思います。
項目名を変えるときは下記のように変更が可能です。
print(df.columns) #これで項目名一覧の取得が可能
df.columns = ['new_col1', 'new_col2', 'new_col3']
自分で作成しclassでも活用したいなと思いつつもどういうときに使用するかが
明確でなかったので、言語化してみました。