Python - アクセス修飾子

こんにちは、Pythonプログラマー志望の皆さん!今日は、Pythonの中でのアクセス修飾子の世界に魅力的な旅を始めます。プログラミングが初めての方でも心配しないでください。私はこの概念をステップバイステップに説明しながら、たくさんの例と説明を提供します。では、いきましょう!

Python - Access Modifiers

Pythonのアクセス修飾子

オブジェクト指向プログラミングにおいて、アクセス修飾子はクラスメンバー(属性とメソッド)の可視性とアクセス可能性を制御するために使用されます。多くのプログラミング言語は厳格なアクセス修飾子を持っていますが、Pythonはよりリラックスしたアプローチを取っています。"私たちは皆、同意した大人です"という哲学を持っています。

Pythonには3種類のアクセス修飾子があります:

  1. 公開(Public)
  2. 保護(Protected)
  3. 私有(Private)

それぞれを例とともに見ていきましょう。

公開メンバー

Pythonでは、すべてのメンバーはデフォルトで公開です。これは、クラスの外部からアクセスできることを意味します。以下はその例です:

class Student:
def __init__(self, name, age):
self.name = name  # 公開属性
self.age = age    # 公開属性

def display_info(self):  # 公開メソッド
print(f"Name: {self.name}, Age: {self.age}")

# Studentのインスタンスを作成
student1 = Student("Alice", 20)

# 公開メンバーにアクセス
print(student1.name)  # 出力: Alice
student1.display_info()  # 出力: Name: Alice, Age: 20

この例では、nameage、およびdisplay_info()はすべて公開メンバーです。クラスの外部から直接アクセスできます。

保護メンバー

保護メンバーは、メンバー名の前にシングルアンダースコア(_)を付けて示されます。これらは本当にプライベートではなく、クラスの外部からもアクセスできますが、内部使用のみとして扱う慣習です。

class Employee:
def __init__(self, name, salary):
self._name = name      # 保護属性
self._salary = salary  # 保護属性

def _display_salary(self):  # 保護メソッド
print(f"{self._name}'s salary is ${self._salary}")

# Employeeのインスタンスを作成
emp1 = Employee("Bob", 50000)

# 保護メンバーにアクセス(注:これは可能ですが推奨されません)
print(emp1._name)  # 出力: Bob
emp1._display_salary()  # 出力: Bob's salary is $50000

_name_salary、および_display_salary()にはアクセスできますが、クラスやサブクラスの外部からアクセスすることは通常お勧めしません。

私有メンバー

私有メンバーは、メンバー名の前にダブルアンダースコア(__)を付けて示されます。Pythonはこれらのメンバーに対して名前の変換を行い、クラスの外部からのアクセスを難しくします(ただし不可能ではありません)。

class BankAccount:
def __init__(self, account_number, balance):
self.__account_number = account_number  # 私有属性
self.__balance = balance                # 私有属性

def __display_balance(self):  # 私有メソッド
print(f"Balance: ${self.__balance}")

def public_display(self):
self.__display_balance()

# BankAccountのインスタンスを作成
account1 = BankAccount("123456", 1000)

# 私有メンバーにアクセスしようとする
# print(account1.__account_number)  # これはAttributeErrorを引き起こします
# account1.__display_balance()      # これもAttributeErrorを引き起こします

# 公開メソッドを通じて私有メソッドにアクセス
account1.public_display()  # 出力: Balance: $1000

この例では、__account_number__balance、および__display_balance()はすべて私有メンバーです。クラスの外部から直接アクセスしようとするとAttributeErrorが引き起こされます。

名前の変換

私が私有メンバーが本当にプライベートではないと述べたのを覚えていますか?これは名前の変換というメカニズムがあるためです。ダブルアンダースコアを使って私有メンバーを作成すると、Pythonは内部でその名前を変更し、誤ってアクセスするのを難しくします。

以下はその仕組みです:

class NameManglingDemo:
def __init__(self):
self.__private_var = "I'm private!"

demo = NameManglingDemo()
print(dir(demo))
# 出力: [..., '_NameManglingDemo__private_var', ...]

# 名前の変換された名前を使って私有変数にアクセス
print(demo._NameManglingDemo__private_var)  # 出力: I'm private!

ご覧のように、Pythonは__private_var_NameManglingDemo__private_varに名前を変更します。これが名前の変換です!

Pythonのプロパティオブジェクト

Pythonのproperty()関数は、ビルトイン関数で、プロパティオブジェクトを作成して返します。これは、クラス属性にゲッター、セッター、およびデリーターメソッドを追加する方法です。

以下はその例です:

class Temperature:
def __init__(self, celsius):
self._celsius = celsius

def get_fahrenheit(self):
return (self._celsius * 9/5) + 32

def set_fahrenheit(self, fahrenheit):
self._celsius = (fahrenheit - 32) * 5/9

fahrenheit = property(get_fahrenheit, set_fahrenheit)

# プロパティを使用
temp = Temperature(25)
print(temp.fahrenheit)  # 出力: 77.0

temp.fahrenheit = 86
print(temp._celsius)  # 出力: 30.0

この例では、fahrenheitはプロパティで、内部では摂氏で保存されている温度を華氏で取得および設定することができます。

ゲッターとセッターメソッド

ゲッターとセッターは、クラス属性の値を取得および設定するためのメソッドです。これらは、プライベート属性にアクセスし、同時に封筒を保つ方法を提供します。

以下は、@propertyデコレータを使用してゲッターとセッターを実装するよりPythonらしい方法の例です:

class Person:
def __init__(self, name, age):
self._name = name
self._age = age

@property
def name(self):
return self._name

@name.setter
def name(self, value):
if not isinstance(value, str):
raise ValueError("Name must be a string")
self._name = value

@property
def age(self):
return self._age

@age.setter
def age(self, value):
if not isinstance(value, int) or value < 0:
raise ValueError("Age must be a positive integer")
self._age = value

# ゲッターとセッターを使用
person = Person("Charlie", 30)
print(person.name)  # 出力: Charlie

person.name = "David"
print(person.name)  # 出力: David

try:
person.age = -5
except ValueError as e:
print(e)  # 出力: Age must be a positive integer

この例では、nameageのゲッターとセッターを作成しました。セッターメソッドには、設定される値が特定の基準を満たすことを確認するバリデーションを含めています。

以下は、今回説明したメソッドをまとめた表です(Markdown形式):

メソッド 説明
公開 どこからでもアクセス可能 self.name
保護 クラスおよびサブクラス内でアクセス可能(慣習) self._name
私有 名前の変換によりアクセスを制限 self.__name
プロパティ プロパティオブジェクトを作成 property(get_method, set_method)
ゲッター 属性の値を取得するメソッド @property
セッター 属性の値を設定するメソッド @attribute.setter

そして、それでお終いです!Pythonのアクセス制御について、名前の変換、プロパティオブジェクト、およびゲッターやセッターメソッドについてカバーしました。Pythonのアクセス制御は、厳格な規則よりも慣習と信頼に基づいていることを覚えておいてください。Pythonの旅を続ける中で、この柔軟性はクリーンで読みやすいコードを書くのに役立ち、同時に必要な場面で封筒を実装する方法を提供します。

継続的に练习し、好奇心を失わずに、幸せなコーディングを!

Credits: Image by storyset