Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

【Python入門】組み込み関数property()と、ゲッターやセッターについての解説

Pythonの組み込み関数property()と、そのゲッターやセッターについての解説

前回の記事においてPythonのデコレータの1種である@propertyについて解説しましたが、その@propertyの仕組みについては組み込み関数property()が大きな役割を果たしています。

そこで今回はPythonの組み込み関数の1つ、property()とそれに関係の深いゲッターとセッターというメソッドにつても解説します。

前提知識:@property

property()とは

Pythonの組み込み関数property()は、プロパティ属性という特殊な(?)オブジェクトを作成する関数です。使い方ですが次のとおりです。

property(,,, ④)
引数指定するもの
ゲッターとなるメソッド
セッターとなるメソッド
デリーターとなるメソッド
ドキュメント文字列

今回の解説では次の項目でまず引数①のゲッターを指定するコードを見ていきましょう。

property()とゲッターについて

ゲッターとは

ゲッターとは、ロボットのことではありません。Pythonにおけるゲッターとは、変数の値を取得するためだけの専用のメソッドのことです。このゲッター(メソッド)には値を返す「return」文が使われます。

ゲッターの使い方

上の@propertyの知識とあわせて、次のコードを見てください。

class C:

    def __init__(self):
        self._text = "推しの子"
    
    # ゲッター
    def getter(self):
        return self._text

    
    # 組み込み関数property()を使ってproperty属性のオブジェクトtextを作成
    text = property(getter)
  
c = C()
c._text  # ==> '推しの子'
c.text  # ==> '推しの子' (c._textと同じ結果)

この最終行の

c.text

実際には、property()関数の第1引数として設定されているgetterを呼び出して実行していることになります。このtextはproperty属性の特別なオブジェクトです。

そしてクラスからインスタンスを生成して使う場合は、普通は、

インスタンス = クラス()
インスタンス.変数名

とするわけですが、

インスタンス.変数名

この部分はあくまで、インスタンスの変数の値を取得するためだけの書き方です。

したがって、

c.text

この場合も、変数の値を取得するだけのメソッドが動けばいいだけです。そのような変数の値を取得するためだけのメソッドがまさにゲッターと言われるメソッドなのです。読み取り専用メソッドとも言われたりします。値を取得する(読み取る)以外のことはやらないという感じですね。

@propertyとの関係

上のコードを@propertyを使って書けば、

class C:

    def __init__(self):
        self._text = "推しの子"
    
    @property
    def getter(self):
        return self._text

  
c = C()
c._text  # ==> '推しの子'
c.getter  # ==> '推しの子' (c._textと同じ結果)

このようになります。特に最終行が「c.getter」へと変わっている点に注意してください。

では次にセッターについて見ていきましょう。

property()とセッターについて

セッターとは

ゲッターが変数の値を取得するためだけのメソッドならば、セッターは変数に値を代入するためだけのメソッドです。

セッターの使い方

上のゲッターを使ったコードをそのまま流用し、そこにセッターを実装するコードを少しだけ加えたのが次のコードです。

class C:

    def __init__(self):
        self._text = "推しの子"

    def getter(self):
        return self._text
    
    def setter(self, txt):
        self._text = txt


    text = property(getter, setter)
    
c = C()
c._text  # ==> '推しの子'
c.text  # ==> '推しの子'

c.text = "究極のゲッター!"
c.text  # ==> '究極のゲッター!'

注意すべき変更点は、

  • def setter〜の部分を追加
  • text = property(getter) から、text = property(getter, setter)へ変更
  • 「c.text = “究極のゲッター!”」という代入文の追加

の3点です。

そしてpropety属性のオブジェクトを作った場合には、代入文の形式を使って、

インスタンス.property属性のオブジェクト = 代入したい情報

このような書き方をすると、自動的にセッター(今回はsetterというメソッド)が呼び出されて、それが実行されることになります。そういう仕組になっています。

セッターとは「セットするもの」という意味ですので、代入文を使って変数に値を代入している処理を担当しているわけです。

@propetyとの関係

ゲッターの場合と同様に、このセッターを使った処理も@propertyを使った表現で書き換えることが可能です。次のようになります。

class C:

    def __init__(self):
        self._text = "推しの子"
    
    @property
    def get_value(self):
        return self._text
     
    @get_value.setter
    def set_value(self, txt):
        self._text = txt


c = C()
c._text  # ==> '推しの子'

# c.textから変更
c.get_value  # ==> '推しの子'

# c.text = "究極のゲッター!"から変更
c.set_value = "究極のゲッター!"
# c.textから変更
c.get_value  # ==> '究極のゲッター!'

上のゲッターのコードとだいたいは同じなのですが、いくつかの変更を加えています。その変更の理由とコードの簡単な解説は次のようになります。

  • 6行目に@propertyメソッドを加えることで、自動的にget_valueという名前のプロパティ属性のオブジェクトが作成される。かつ、property()の第1引数としてメソッドget_valueが指定される
  • プロパティ属性のオブジェクトは最初からgetter、setter、deleter、という3のメソッドを持っているため、それらと名前が重複しないようメソッドの名前を変更した
  • 10行目@get_value.setterデコレータにより、メソッドset_valueはget_valueオブジェクトのメソッドのsetterになる→property()の第2引数としてset_valueが指定される

Pythonではゲッターとセッターは推奨されていない

以上のようにproperty()とゲッター/セッターについての解説をしてきましたが、実はPythonにおいてはゲッターやセッターそのものを単独で使うことは推奨されていません。どうしてもコードが複雑になり、わかりにくくなると考えられているからです。

しかしそれらを使ったほうが実際に便利な場面もあるため、@propertyを使うことでそれらを実質的に実装するというシステムになっています。

@classmethodと@staticmethodについて

クラス内部で使われるデコレータとしては、クラスメソッド(@classmethod)とスタティックメソッド(@staticmethod)もよく使われるものです。これらについても次の記事で解説を書いています。

Pythonのおすすめ動画講座

忙しい毎日でも短時間でPythonを効率よく学習するには動画学習がおすすめです。次の記事でおすすめの動画をまとめています。