生成AIと学ぶPython23: カプセル、アクセス修飾子、setter、getter
カプセル化とは
カプセル化とは、データとその操作(つまり、関数やメソッド)を結びつけるオブジェクト指向プログラミングの原則です。
これにより、オブジェクトの内部状態はそのオブジェクト自身のメソッドによってのみ変更され、外部から直接アクセスされることはありません。これは、コードの保守性と信頼性を向上させ、誤った操作によるバグの可能性を減らします。
Pythonでは、アクセス修飾子を使ってカプセル化を実現します。Pythonには次の3つのアクセス修飾子があります:
Public: これはデフォルトの修飾子で、メンバ変数やメソッドが公開され、外部から直接アクセスできることを意味します。例:name
Protected: 名前の前にアンダースコア _ が付いたメンバ変数やメソッドは、そのクラスおよびそのサブクラスからのみアクセスできることを意味します(ただし、これは主に慣習に過ぎず、Pythonは実際にはこれを強制しません)。例:_name
Private: 名前の前にダブルアンダースコア __ が付いたメンバ変数やメソッドは、そのクラスからのみアクセスできることを意味します。Pythonでは、これらのメンバに直接アクセスすると、AttributeErrorが発生します。例:__name
class MyClass:
def __init__(self):
self.name = "Public"
self._name = "Protected"
self.__name = "Private"
def access_private_member(self):
return self.__name
obj = MyClass()
print(obj.name) # Outputs: Public
print(obj._name) # Outputs: Protected
print(obj.__name) # Raises AttributeError: 'MyClass' object has no attribute '__name'
print(obj.access_private_member()) # Outputs: Private
この例では、__nameはMyClassのプライベートメンバであり、そのクラスのメソッドからのみアクセスできます。したがって、access_private_memberメソッドを通じて__nameにアクセスすることはできますが、直接アクセスしようとするとエラーが発生します。
setterとgetter
Pythonでは、プロパティの値を取得したり設定したりするために、ゲッター(getter)とセッター(setter)メソッドを使用することができます。これらのメソッドは、データのカプセル化を実現するための重要なツールです。
ゲッターとセッターを使用することで、クラスの内部データに直接アクセスする代わりに、メソッドを通じて間接的にアクセスします。これにより、値の検証、エラーチェック、追加のアクションの実行などを行うことができます。
class Person:
def __init__(self, name):
self._name = name # _name is protected
@property
def name(self):
print("Getting name")
return self._name
@name.setter
def name(self, value):
if isinstance(value, str):
print("Setting name to " + value)
self._name = value
else:
raise TypeError("Name must be a string.")
このクラスでは、_nameプロパティは保護されており、直接アクセスすることはできません。その代わりに、nameという名前のゲッターとセッターメソッドが提供されています。これらのメソッドは、デコレータを使って定義されており、プロパティを直接アクセスするかのように使うことができます。
person = Person("Alice")
print(person.name) # Outputs: Getting name\nAlice
person.name = "Bob" # Outputs: Setting name to Bob
print(person.name) # Outputs: Getting name\nBob
person.name = 123 # Raises: TypeError: Name must be a string.
このように、Pythonのゲッターとセッターは、クラスの外部からのデータアクセスを管理し、データの整合性を保つための重要な手段です。
setterとgetterのベストプラクティス
Pythonではプロパティのゲッターとセッター以外にもいくつかの特定の目的に使用することができます。
class Circle:
def __init__(self, radius):
self._radius = radius
@property
def radius(self):
return self._radius
@radius.setter
def radius(self, value):
if value >= 0:
self._radius = value
else:
raise ValueError("Radius cannot be negative.")
@property
def diameter(self):
return self._radius * 2
@property
def area(self):
return 3.141592653589793 * self._radius ** 2
この例では、Circle クラスは radius、diameter、および area という3つのプロパティを提供します。radius プロパティはセッターを使用して値が負でないことを保証します。diameter と area は計算されるプロパティであり、ゲッターのみを提供します。