Python : クラスの使い方 3

TwitterFacebookHatena
  • 公開:2021-10-12
  • 更新:2023-10-26
  • 文章量:2163
  • Python

TL;DR

クラスにおけるプロパティ(@property)とは、インスタンスメソッドを、外部からアクセスしたり、変更できないようにする機能である。

プロパティのポイント

  • ゲッター、セッターは、非公開属性の値を読み書きする
  • @で始まる文をデコレータと呼ぶ
  • def 文で機能を定義する
  • property と setter のインスタンスメソッド名は同じにする
  • インスタンスメソッドを()を付けずに呼び出せる
  • 属性にアンダースコア(_)をつけるとプライベート変数になる

英語において、property は「所有している性質、属性」、setter は「値を設定」などの意味があるが、Python においては次の性質がある。

@property @インスタンスメソッド.setter
getter setter
属性アクセス(値の取得時) 新しい値を設定する
ゲッターメソッドの前 セッターメソッドの前
class クラス名:
    def __init__(self, 仮引数):
        self.インスタンス変数 = 仮引数

    @property
    def インスタンスメソッド(self):
        return self.インスタンス変数

    @インスタンスメソッド.setter
    def インスタンスメソッド(self, 仮引数):
        self.インスタンス変数 = 仮引数

@property

次のコードは、正方形の面積を求めるものである。edge 属性を書き換えている。

class Square:
    def __init__(self, edge):
        self._edge = edge
    @property
    def calc(self):
        return self._edge ** 2

square = Square(5)

square.calc
# 25

square.edge = 10
square.calc # 100

@プロパティ.setter

次のコードの @name.setter が、セッターである。setter は値が代入されたときに呼び出される。メソッド名は、@property を付けたメソッド名をそのまま利用する必要がある。

class A:
    def __init__(self, input_name):
        self.hidden_name = input_name

    @property # 値が呼び出されたとき
    def name(self):
        print('getter')
        return self.hidden_name

    @name.setter # 値が代入されたとき
    def name(self, input_name):
        print('setter')
        self.hidden_name = input_name


a = A('値1')
a.name # getter 値1

a.name = '値2' # setter
a.name # getter 値2

マングリング(名前装飾)

そもそも Python には private 変数がないが、それに近いことはできる。

属性にアンダースコア(_)をつけるとプライベート変数になる。インスタンスのユーザーには非公開にしておきたいときに使う。

アンダースコアを 2 つ(__)つけた場合、マングリングが働く。マングリングをつかうと、インスタンス変数にアクセスできなくなる。サブクラスでの名前衝突を防ぐために使われる

次に示すコードのように、実際に属性が非公開になるわけではないが、意図しないアクセスをある程度防ぐことができる。

class A:
    def __init__(self, input_name):
        self.__name = input_name

    @property
    def name(self):
        print('getter')
        return self.__name

    @name.setter
    def name(self, input_name):
        print('setter')
        self.__name = input_name

a = A('hoge')
a.name
# getter
# 'hoge'

a.name = 'add text'
# setter

a.name
# getter
# 'add text'

a.__name
# __name 属性にはアクセスできない
# AttributeError: 'A' object has no attribute '__name'

# しかし、規則を知っていればアクセス可能になってしまう
a._A__name
# 'hoge'

Python : クラスの使い方 3