Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonクラスにおけるゲッター(Getter)とセッター(Setter)とは?基本とPythonicな書き方を解説

ゲッター(Getter)とセッター(Setter)は、多くのオブジェクト指向プログラミング言語において、データカプセル化の原則を実現するために使われるメソッドです。「ミューテーターメソッド(mutator methods)」と呼ばれることもあります。データカプセル化とは、データと、そのデータを操作するメソッドをひとまとめにすることを指します。ここでいうメソッドとは、データを取得するためのゲッターと、データを変更するためのセッターのことです。この原則に従うと、クラスの属性はプライベートに設定され、外部のコードから隠蔽・保護されます。

Pythonでは@propertyを使うのが定石

残念ながら、「正しいPythonのクラスは、ゲッターとセッターを使ってプライベート属性をカプセル化すべきだ」という誤解が広く浸透しています。しかし、いちいちゲッターとセッターを明示的に呼び出すスタイルは、必ずしも簡潔でエレガントとは言えません。

Pythonらしい(Pythonicな)やり方は、プロパティ(property)を使うことです。値を取得するためのメソッドには「@property」デコレーターを付け、セッターとして機能させたいメソッドには「@x.setter」のようなデコレーターを付けます。こうすることで、通常の属性アクセスと同じ構文のまま、内部で検証処理などを挟むことができます。

コード例:property()を使ったゲッターとセッター

以下は、property()関数を使ってゲッターとセッターを実装した例です。

class P:
    def __init__(self, x):
        self.__set_x(x)

    def __get_x(self):
        return self.__x

    def __set_x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x

    x = property(__get_x, __set_x)

この例では、属性 __x が名前修飾(ネームマングリング)によりプライベート化され、外部から直接アクセスしにくくなっています。__set_x メソッドが値の妥当性チェックを担当し、0未満の値は0に、1000を超える値は1000に制限されます。

最後の行の x = property(__get_x, __set_x) により、これらのメソッドがプロパティとして登録されます。その結果、次のように普通の属性と同じ構文で値の取得・設定が可能になります。

p = P(500)
print(p.x)    # 500

p.x = 2000
print(p.x)    # 1000(上限値に制限される)

このようにpropertyを使えば、カプセル化の恩恵を受けながら、呼び出し側のコードはシンプルで読みやすいまま保つことができます。これこそがPythonにおける推奨されるアプローチです。

  1. Pythonの識別子とは?命名ルールと規則をわかりやすく解説

    Pythonの識別子(identifier)とはPythonにおける識別子(identifier)とは、変数、関数、クラス、モジュールなどのオブジェクトを一意に特定するために付ける名前のことです。プログラム内でデータや処理を扱ううえで、識別子は最も基本的な要素の一つといえます。識別子の基本的なルール識別子は、英字(A〜Z、a〜z)またはアンダースコア(_)で始まり、その後に0個以上の英字・アンダースコア・数字(0〜9)が続く形で構成されます。一方で、Pythonでは「@」「$」「%」などの記号を識別子に含めることはできません。また、Pythonは大文字と小文字を区別する言語であるため、「Man

  2. Pythonの継承とは?単一継承と階層継承の基本をサンプルコードで解説

    本記事では、Python 3.xにおける継承(インヘリタンス)とクラスの拡張方法について詳しく解説します。 継承とは、現実世界のモノや概念の関係性を自然に表現できる、オブジェクト指向プログラミングの中核となる仕組みです。継承を活用すると、次のようなメリットが得られます。 再利用性:すでに書いたコードを流用でき、重複を削減できる 推移性:クラス間の関係を連鎖的に引き継げる 開発速度の向上:ゼロから書かずに済むため、短期間で開発できる 保守性・拡張性:既存クラスを壊さずに機能を追加しやすい 継承の5つの種類 Pythonの継承は、その構造によって主に以下の5種類に分類されます。 単一継承(