Pythonのカプセル化とselfについて

投稿日: 2024年4月1日

カプセル化っていう言葉がありますけど実際カプセル化って何ですか?

知らずに使っていることもあるからじっくり解説するね。

カプセル化とは、オブジェクト指向プログラミングにおける重要な概念の一つで、クラスの内部実装を隠蔽し、外部からの直接的なアクセスを制限する手法です。
これにより、オブジェクトのデータ(属性)とそのデータを操作するメソッドを一つの「カプセル」にまとめることができます。カプセル化の主な目的は、以下の二つです。

データの隠蔽

クラスの内部データを外部から直接アクセスできないようにすることで、オブジェクトの状態を不正に変更されることを防ぎます。これは、オブジェクトの状態を安全に保ち、不意の変更や予期しないエラーを避けるために重要です。

インターフェースの提供

クラスが外部に公開するメソッド(インターフェース)を通じてのみ、オブジェクトの状態を変更または取得できるようにします。これにより、クラスの使用方法を明確にし、クラスの内部実装が変更された場合でも、クラスの使用者に影響を与えにくくします。

カプセル化の実装方法

Pythonでは、属性やメソッドの前にアンダースコア_(シングル)またはダブルアンダースコア__(ダブル)を付けることでカプセル化を実現します。

  • _(シングルアンダースコア): この属性やメソッドは内部使用のためのものであり、外部からのアクセスは推奨されないことを意味します(しかし、技術的にはアクセス可能)。
  • __(ダブルアンダースコア): クラス内部でのみ使用されるプライベートメンバーであり、外部から直接アクセスすることはできません。Pythonでは、名前のマングリング(クラス名をプレフィックスとして追加すること)を行うことで、これを実現します。

カプセル化の例

class BankAccount:
    def __init__(self, initial_balance):
        self.__balance = initial_balance  # プライベート属性

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False

    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return True
        return False

    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
print(account.deposit(500))  # True
print(account.withdraw(200))  # True
print(account.get_balance())  # 1300

この例では、__balanceはダブルアンダースコアで定義されているため、BankAccountクラスの外部からは直接アクセスできません。deposit、withdraw、get_balanceメソッドを通じてのみ、口座の残高を安全に管理できます。

カプセル化を使用することで、クラスの利用者がクラスの内部実装に依存することなく、クラスの機能を利用できるようになります。これにより、ソフトウェアの保守性と拡張性が向上します。

引数に使われるselfって何ですか?

selfはPythonにおいて慣例的に使われる名前で可読性を高めるためにあえてその名称を使っているんだよ。

selfについて

selfはPythonにおいて慣例的に使われる名前ですが、Pythonの言語仕様に強制されるわけではありません。
つまり、selfの代わりに別の名前を使用することも可能ですが、一般的なPythonのコーディング規約に従い、可読性を保つためにselfを使うことが推奨されます。

selfの使い方

selfはPythonのオブジェクト指向プログラミングにおいて、クラスのメソッド内で使用される特別な引数で、現在のインスタンスを参照します。
クラス定義内のメソッドが呼び出されるとき、Pythonは自動的にそのメソッドの最初の引数としてselfを渡します。
これにより、メソッド内からそのインスタンスの属性や他のメソッドにアクセスすることが可能になります。

クラスのメソッドを定義する際、第一引数としてselfを明示的に記述する必要があります。
しかし、メソッドを呼び出す際にselfを渡す必要はありません。Pythonが自動的に現在のオブジェクトをselfとしてメソッドに渡します。

class MyClass:
    def __init__(self, value):
        self.my_attribute = value  # インスタンス変数への値の設定

    def my_method(self):
        print(f"属性の値は{self.my_attribute}です。")  # インスタンス変数へのアクセス

# インスタンスの作成とメソッドの呼び出し
my_instance = MyClass("何らかの値")
my_instance.my_method()  # 出力: 属性の値は何らかの値です。

この例では、MyClassには2つのメソッドがあります:init(コンストラクタ)とmy_methodです。両方のメソッドでselfを使用して、それぞれインスタンス変数my_attributeの設定とアクセスを行っています。

selfの重要性

  • インスタンス変数の定義とアクセス:selfを使用して、クラスのインスタンスごとに異なる状態(インスタンス変数)を保持できます。
  • メソッドの呼び出し:selfを通じて、同じクラスの他のメソッドを呼び出すことができます。

selfはPythonのオブジェクト指向プログラミングにおける重要な概念であり、クラスメソッド内で現在のインスタンスにアクセスするための標準的な方法を提供します。

記事