Pythonにおけるクラス変数とインスタンス変数の違いと振る舞い

クラス変数(Class Variables)

クラス変数は、クラス定義の直下(クラス名前空間内)で宣言された変数です。これらはクラス自体に属し、すべてのインスタンスで共有されます。クラス名を用いて直接参照や更新が可能です。

class ServerConfig:
    max_connections = 100

    def show_config(self):
        # クラス名経由でクラス変数にアクセス
        print(ServerConfig.max_connections)

# クラス名による参照と更新
print(ServerConfig.max_connections)  # 100
ServerConfig.max_connections = 200

config_instance = ServerConfig()
config_instance.show_config()  # 200

Pythonでは、インスタンスオブジェクトからもクラス変数にアクセスできます。しかし、インスタンス経由でクラス変数と同じ名前の属性に値を代入しようとすると、クラス変数が更新されるのではなく、そのインスタンス固有のインスタンス変数が新規に作成(属性のシャドーイング)されます。

class ServerConfig:
    max_connections = 100

    def show_config(self):
        # self(インスタンス)経由でアクセス
        print(self.max_connections)

server = ServerConfig()
print(server.max_connections)  # 100(クラス変数を参照)

# インスタンス経由で代入
server.max_connections = 300
server.show_config()  # 300(インスタンス変数が作成され、クラス変数を隠蔽する)
print(server.max_connections)  # 300

# クラス変数自体は変更されていない
print(ServerConfig.max_connections)  # 100

インスタンス変数(Instance Variables)

インスタンス変数は、各オブジェクト(インスタンス)ごとに独立して保持されるデータです。通常、メソッド内(特に __init__ などの初期化メソッド)で self.変数名 の形式で定義されます。

class DatabaseConnection:
    default_host = "localhost"

    def __init__(self, db_name):
        # インスタンス変数の定義
        self.db_name = db_name

    def display_info(self):
        print(f"DB: {self.db_name}, Host: {self.default_host}")

conn1 = DatabaseConnection("users_db")
conn2 = DatabaseConnection("orders_db")

conn1.display_info()  # DB: users_db, Host: localhost
conn2.display_info()  # DB: orders_db, Host: localhost

# クラス変数を変更しても、インスタンス変数には影響しない
DatabaseConnection.default_host = "192.168.1.1"
conn1.display_info()  # DB: users_db, Host: 192.168.1.1(まだインスタンス変数がないためクラス変数を参照)

あるインスタンスのインスタンス変数を変更しても、他のインスタンスやクラス変数には一切影響を与えません。これは、各インスタンスが独自の属性辞書を持っているためです。

class DatabaseConnection:
    default_host = "localhost"

    def __init__(self, db_name):
        self.db_name = db_name
        self.host = self.default_host  # インスタンス変数としてホストを保持

    def change_host(self, new_host):
        self.host = new_host

conn_a = DatabaseConnection("analytics")
conn_b = DatabaseConnection("logs")

# conn_aのインスタンス変数だけを変更
conn_a.change_host("10.0.0.5")

print(conn_a.host)  # 10.0.0.5(インスタンス変数が更新された)
print(conn_b.host)  # localhost(他のインスタンスには影響しない)
print(DatabaseConnection.default_host)  # localhost(クラス変数にも影響しない)

タグ: Python クラス変数 インスタンス変数 オブジェクト指向 スコープ

10月16日 17:56 投稿