PYTHON MEBY

Pythonでカプセル化(private, protected)を実装

この記事では、Pythonにおけるカプセル化、特にprivateとprotectedメンバ変数、メソッドの実装方法について解説します。Pythonでは厳密なprivateやprotectedキーワードはありませんが、命名規則とデコレータを用いて実現できます。

目次

Pythonにおけるカプセル化とは?

カプセル化とは、オブジェクトの内部状態を外部から直接アクセスできないように保護する設計手法です。データとそれを操作するメソッドをまとめて管理することで、コードの保守性と安全性を高めることができます。Pythonでは、厳格なアクセス修飾子(private, protected, public)はありませんが、命名規則とデコレータを用いてカプセル化を実現できます。

privateメンバ変数とメソッドの実装

Pythonでは、変数名またはメソッド名にダブルアンダースコア(__)を先頭に付けることで、名前マングリングという仕組みによって、外部からの直接アクセスを難しくすることができます。ただし、完全にアクセスできないわけではなく、内部的には__<クラス名>__<変数名> のように名前が変更されるため、意図的にアクセスすることは可能です。

class MyClass:
    def __init__(self, value):
        self.__private_var = value

    def __private_method(self):
        print("This is a private method.")

    def access_private(self):
        print(self.__private_var)
        self.__private_method()

object = MyClass(10)
object.access_private() # 出力: 10, This is a private method.
# object.__private_var # AttributeError: 'MyClass' object has no attribute '__private_var'
# object.__private_method() # AttributeError: 'MyClass' object has no attribute '__private_method'

上記のように、ダブルアンダースコアで始まるメンバ変数やメソッドは、直接アクセスしようとするとAttributeErrorが発生します。

protectedメンバ変数とメソッドの実装

protectedメンバは、クラスとそのサブクラスからのみアクセス可能なメンバです。Pythonでは、変数名またはメソッド名にシングルアンダースコア(_)を先頭に付けることで、protectedメンバとして扱います。これはあくまでも慣習的なものであり、強制力はありません。

class MyClass:
    def __init__(self, value):
        self._protected_var = value

    def _protected_method(self):
        print("This is a protected method.")

class MySubclass(MyClass):
    def access_protected(self):
        print(self._protected_var)
        self._protected_method()

object = MySubclass(20)
object.access_protected() # 出力: 20, This is a protected method.
print(object._protected_var) # 出力: 20

上記のように、シングルアンダースコアで始まるメンバ変数やメソッドは、サブクラスからアクセス可能です。

_namemangling(名前マングリング)

Pythonのname manglingは、privateメンバを外部からの直接アクセスから守るための仕組みです。ダブルアンダースコアで始まる名前は、クラス名とアンダースコアを連結した特殊な名前に変更されます。これにより、意図しないアクセスを防ぎます。しかし、完全にアクセスできないわけではなく、内部的にはアクセス可能です。

デコレータによるカプセル化

プロパティデコレータを使うことで、より洗練されたカプセル化を実現できます。setter, getter, deleter を定義することで、メンバ変数へのアクセスを制御できます。

class MyClass:
    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, new_value):
        if new_value > 0:
            self._value = new_value
        else:
            raise ValueError("Value must be positive.")

object = MyClass(5)
print(object.value) # 出力: 5
object.value = 10
print(object.value) # 出力: 10
try:
    object.value = -1
except ValueError as e:
    print(e) # 出力: Value must be positive.

カプセル化のメリットとデメリット

カプセル化によって、コードの保守性、可読性、安全性を向上させることができます。しかし、過剰なカプセル化はコードを複雑化させる可能性があります。適切なバランスを保つことが重要です。

関連記事