チャポケのブログ

勉強したことをまとめておく。

Python クラス

クラスの定義、クラスの利用

クラスは、classを使って次のように定義して、利用する。

# クラスの定義
class Animal:
    count = 0 # クラス変数
    
    def __init__(self, name): # コンストラクタ
        Animal.count += 1
        self.name = name # インスタンス変数
        print("公園に" + self.name + "が来た")

    def __del__(self): # デストラクタ
        Animal.count -= 1
        print("公園から" + self.name + "が出て行った")
    
    def eat(self, food): # メソッド
        print(self.name + "は" + food + "を食べた")
    
    @classmethod
    def showCount(cls): # クラスメソッド
        print("公園に" + str(Animal.count) + "匹の動物がいる")

# クラスの利用
print(Animal.count)      # 0

animal1 = Animal("ポチ") # 公園にポチが来た
animal1.eat("肉")        # ポチは肉を食べた
Animal.showCount()       # 公園に1匹の動物がいる

print(Animal.count)      # 1

animal2 = Animal("タマ") # 公園にタマが来た
Animal.showCount()       # 公園に2匹の動物がいる

animal3 = Animal("ハチ") # 公園にハチが来た
Animal.showCount()       # 公園に3匹の動物がいる

del animal2              # 公園からタマが出て行った
Animal.showCount()       # 公園に2匹の動物がいる

# プログラム終了時に、残りのインスタンスが破棄されて
                         # 公園からポチが出て行った。
                         # 公園からハチが出て行った。

メソッド

14行目。メソッド(クラス内の関数)は、必ず第一引数selfをとる。
25行目。メソッド呼び出しでは、引数selfは書かないが、
メソッドを呼び出すと、メソッドの第一引数selfに、メソッドを呼び出したインスタンス自身が渡される。

コンストラクタ、インスタンス変数、デストラク

5行目。コンストラクタは、__init__(self)で定義する。
クラスのインスタンス生成時に自動的に呼ばれる特別なメソッドで、インスタンスの初期化に使用する。

7行目。インスタンス変数は、self.変数で定義する。
インスタンスが持つ変数で、インスタンスが破棄されるまで保持される。

10行目。デストラクタは、__del__(self)で定義する。
クラスのインスタンスの破棄時に自動的に呼ばれる特別なメソッドで、インスタンスの後始末に使用する。

クラス変数、クラスメソッド

3行目。クラス変数は、クラスの直下で変数を定義する。
全てのインスタンスで共有して使用できる変数。
6,11,19行目。参照するときは、クラス名.クラス変数名とする。
22,28行目。インスタンスからでなくても、インスタンスを生成する前からでも、アクセス可能。

17行目。クラスメソッドは、メソッド定義の前にデコレータ@classmethodを付けて、
更にメソッドに必ず第一引数clsをとるようにする。
26,31,34,37行目。呼び出すときは、クラス名.クラスメソッド名()とする。
クラスメソッド呼び出しでは、引数clsは書かないが、
クラスメソッドを呼び出すと、第一引数clsに、クラス自身が渡される。

アクセス制限:プライベート変数、プライベートメソッド

アンダーバー2つ("__")から始まる変数を定義すると、プライベート変数となる。
アンダーバー2つ("__")から始まるメソッドを定義すると、プライベートメソッドとなる。
クラス変数、クラスメソッドも同様に、プライベートクラス変数プライベートクラスメソッドになる。
これらは、クラスの中だけから呼び出し又は参照できる。クラスの外から呼び出し又は参照するとエラーになる。

# クラスの定義
class Animal:
    __count = 0 # プライベートクラス変数
    
    def __init__(self, name): # コンストラクタ
        Animal.__count += 1
        self.__name = name # プライベートインスタンス変数
        print("公園に" + self.__name + "が来た")
        self.__eat("エサ")

    def __del__(self): # デストラクタ
        Animal.__count -= 1
        print("公園から" + self.__name + "が出て行った")
    
    def __eat(self, food): # プライベートメソッド
        print(self.__name + "は" + food + "を食べた")
    
    @classmethod
    def showCount(cls): # クラスメソッド
        print("公園に" + str(Animal.__count) + "匹の動物がいる")

# クラスの利用
#print(Animal.__count)   # コメントアウトを外すとAttributeErrorとなる。

animal1 = Animal("ポチ") # 公園にポチが来た
                         # ポチはエサを食べた
#animal1.__eat("肉")     # コメントアウトを外すとAttributeErrorとなる。
Animal.showCount()       # 公園に1匹の動物がいる

# プログラム終了時に、残りのインスタンスが破棄されて
                         # 公園からポチが出て行った。

3行目。プライベートクラス変数の定義。
6,12,20行目の参照は正常であるが、
23行目の参照は、クラス外からなのでエラーになる。

7行目。プライベートインスタンス変数の定義。

15行目。プライベートメソッドの定義。
9行目の呼び出しは正常であるが、
27行目の呼び出しは、クラス外からなのでエラーになる。