Pythonのクラスメンバーとアクセス制御

Pythonにおけるクラス構成要素とアクセス修飾子

一. クラスの構成要素の分類

クラスは以下の構成要素に大別されます:

class SampleClass:

    organization = 'TechAcademy'  # クラス変数(共有フィールド)
    __private_key = 'secret123'  # プライベートクラス変数


    def __init__(self, name, level): # コンストラクタ

        self.name = name  # インスタンス変数
        self.__level = level  # プライベートインスタンス変数

    def display(self):  # インスタンスメソッド
        pass

    def __internal(self): # プライベートメソッド
        print('内部処理')

    @classmethod  # クラスメソッド
    def class_method(cls):
        print('クラスレベル操作')

    @staticmethod  # ステートレスメソッド
    def utility():
        print('汎用ユーティリティ')

    @property  # プロパティアクセサ
    def status(self):
        return self.__level

二. クラスメンバーの可視性

2.1 クラスレベルの公開変数

class Base:
    public_data = "共有情報"

    def show(self):
        print(Base.public_data)

class Derived(Base):
    def access(self):
        print(Base.public_data)

Base.public_data       # クラス経由アクセス可能
obj = Base()
obj.show()             # インスタンスメソッド内からアクセス可能
child = Derived()
child.access()         # 派生クラスからアクセス可能

2.2 クラスレベルのプライベート変数

class Base:
    __private_data = "機密情報"

    def reveal(self):
        print(Base.__private_data)

class Derived(Base):
    def try_access(self):
        print(Base.__private_data)

Base.__private_data     # 外部アクセス不可
obj = Base()
obj.__private_data      # インスタンス経由アクセス不可
obj.reveal()            # クラス内部メソッドからアクセス可能
child = Derived()
child.try_access()      # 派生クラスからのアクセス不可

2.3 インスタンス変数の公開アクセス

class User:
    def __init__(self):
        self.username = "public_user"

    def get_name(self):
        print(self.username)

class Admin(User):
    def display(self):
        print(self.username)

user = User()
user.username          # インスタンス直接アクセス
user.get_name()        # メソッド経由アクセス
admin = Admin()
admin.display()        # 派生クラスからのアクセス

2.4 インスタンス変数のプライベート制限

class User:
    def __init__(self):
        self.__username = "private_user"

    def get_name(self):
        print(self.__username)

class Admin(User):
    def display(self):
        print(self.__username)

user = User()
user.__username        # 外部アクセス不可
user.get_name()        # クラス内部メソッドからアクセス可能
admin = Admin()
admin.display()        # 派生クラスからのアクセス不可

2.5 公開メソッドのアクセス

class Engine:
    def start(self):
        print('Engine started')

class Car(Engine):
    def drive(self):
        print('Driving...')

    def use_engine(self):
        self.start()

car = Car()
car.drive()            # 直接メソッド呼び出し
car.use_engine()       # クラス内部からメソッド呼び出し
car.start()            # 派生クラスから親メソッド呼び出し

2.6 プライベートメソッドの制限

class Engine:
    def __start(self):
        print('Engine started internally')

class Car(Engine):
    def __drive(self):
        print('Private driving method')

    def use_engine(self):
        self.__drive()

car = Car()
car.__drive()          # 外部アクセス不可
car.use_engine()       # クラス内部からアクセス可能
car.__start()          # 派生クラスからのアクセス不可

三. 特殊なメソッド種別

3.1 クラスメソッドの活用例

class StudentRegistry:
    __total = 0
    
    def __init__(self, name):
        self.name = name
        StudentRegistry.register()

    @classmethod
    def register(cls):
        cls.__total += 1

    @classmethod
    def count_students(cls):
        return cls.__total

s1 = StudentRegistry("山田")
s2 = StudentRegistry("佐藤")
print(StudentRegistry.count_students())

3.2 ステートレスメソッドの実装

class TimeUtility:
    @staticmethod
    def current_time():
        from datetime import datetime
        return datetime.now().strftime("%H:%M:%S")

print(TimeUtility.current_time())
clock = TimeUtility()
print(clock.current_time())

3.3 プロパティの動的計算

class HealthIndex:
    def __init__(self, weight, height):
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)

person = HealthIndex(70, 1.75)
print(f"BMI: {person.bmi}")

商品価格管理の例:

class Product:
    def __init__(self):
        self._base_price = 5000
        self._discount_rate = 0.9

    @property
    def final_price(self):
        return self._base_price * self._discount_rate

    @final_price.setter
    def final_price(self, new_base):
        self._base_price = new_base

item = Product()
print(item.final_price)
item.final_price = 6000
print(item.final_price)

四. インスタンス判定と継承関係

4.1 isinstanceの使用例:

class Animal:
    pass

class Dog(Animal):
    pass

pet = Dog()
print(isinstance(pet, Dog))
print(isinstance(pet, Animal))

4.2 継承関係の確認:

class Vehicle:
    pass

class Car(Vehicle):
    pass

class Convertible(Car):
    pass

print(issubclass(Car, Vehicle))
print(issubclass(Convertible, Vehicle))

型間の関係確認:

from collections.abc import Sequence

print(isinstance([1,2,3], list))
print(isinstance([1,2,3], Sequence))
print(issubclass(list, Sequence))

タグ: Python OOP クラスメソッド プロパティ 継承

9月10日 21:16 投稿