初学者のためのPython講座　オブジェクト指向編6　クラス変数とクラスメソッド

# クラス変数とクラスメソッド

クッキー型を例に、クラスはオブジェクトの設計図、インスタンスがその実体であると[説明しました](https://qiita.com/kotakahe/items/3de8d471ea871b0a7024)が、クラス自身もインスタンス同様にデータとメソッドを持つことができます。ここからは、クラスに焦点をあてて、特定のオブジェクトに依らない共通のデータとメソッドの扱いについて学習しましょう。



## クラス変数でインスタンスをカウントする

クラス変数を使って、`Cookie`クラスからクッキーが何枚できたかをカウントします。

クッキーの枚数をカウントするには、クッキーインスタンスが生成されるたびにカウントアップする、クラス変数を定義します。クラス変数を初期化メソッドに記述して、初期化メソッドが呼び出されるたびに値が追加されるようにしましょう。

```python
class Cookie:
    name = "クッキー"
    # クッキーの枚数をカウントするクラス変数を定義する
    count = 0
    # 初期化メソッドを定義する
    def __init__(self, taste):
        self.taste = taste
        # クラス変数をカウントアップする
        Cookie.count += 1
        # インスタンスの生成と同時に表示
        print(str(Cookie.count)+"枚目：" + self.taste + self.name)

cookie1 = Cookie("プレーン")
cookie2 = Cookie("チョコ")
cookie3 = Cookie("チョコチップ")
```

実行してみましょう。

```
1枚目：プレーンクッキー
2枚目：チョコクッキー
3枚目：チョコチップクッキー
```

クッキーの枚数がカウントできました。

まずクラス変数は`count = 0`を**初期値**として定義しています。その後の初期化メソッドでは`Cookie.count += 1`と記述することで、**初期化メソッドが呼び出されるたびに追加**されます。
ここで、注意する点が`Cookie.count`となっていることです。**クラス名**`Cookie`を記述することで**クラス変数**を呼び出しています。これを`self`として`self.count`と記述すると**インスタンス変数**を呼び出すことになるため、クラス変数`count`は`0`のままになってしまいます。



## クラスメソッド

クラス変数のようにクラスから呼び出すことができるメソッドのことを**クラスメソッド**といいます。通常はクラス内でメソッドを定義した場合、このメソッドをインスタンスから呼び出すことはできますが、クラスから呼び出すことはできません。通常のメソッドは、クラスメソッドに対して**インスタンスメソッド**といいます。



クラスメソッドを定義するには組み込みのデコレータ`@classmethod`を使います。また、第1引数は`cls`を指定します。これはインスタンスメソッドが`self`で**インスタンス自身**を参照するように、`cls`はメソッド内で**クラス自身**を参照できるようにするための引数です。

クラスメソッドはクラス変数同様、クラスからもインスタンスからも呼び出せるだけでなく、インスタンスを生成しなくても呼び出すことができます。



#### 【書式】クラスメソッドの定義

```python
@classmethod
def メソッド名(cls, 引数2, 引数3,…):
    処理内容
```



また、クラスメソッドを呼び出すときは通常のメソッドと同じように記述します。

#### 【書式】クラスメソッドを実行する

```python
クラス名(またはインスタンス名).メソッド名(引数2, 引数3,…)
```



では、簡単な例でクラスメソッドとインスタンスメソッドの違いを確認しましょう。

```python
class A:
    name = "Aクラス"
    def __init__(self, name):
        self.name = name
    def ins_method(self):
        print(self.name + "メソッド")

    # クラスメソッドを定義する
    @classmethod
    def cl_method(cls):
        print(cls.name + "メソッド")
    
# Aクラスからクラスメソッドを呼び出す
A.cl_method()

# インスタンスを生成して各メソッドを呼び出す
a = A("aインスタンス")
a.ins_method()
a.cl_method()
```

実行してみましょう。

```
Aクラスメソッド
aインスタンスメソッド
Aクラスメソッド
```

このように、クラスメソッドはインスタンスを生成しなくても、クラスのみで呼び出すことができます。また、クラスメソッドもインスタンスメソッドも変数`name`を参照していますが、クラスメソッドではクラス、インスタンスどちらで呼び出してもクラス変数を参照しています。



次に、**クラスを継承した場合のクラスメソッド**について確認しましょう。

```python
class A:
    name = "Aクラス"
    @classmethod
    def cl_method(cls):
        print(cls.name + "メソッド")

# Aクラスを継承してクラス変数nameを更新する
class B(A):
    name = "Bクラス"

# 各クラスからクラスメソッドを呼び出す
A.cl_method()
B.cl_method()
# Aクラスのインスタンスでクラスメソッドを呼び出す
a = A()
a.cl_method()
# Bクラスのインスタンスでクラスメソッドを呼び出す
b = B()
b.cl_method()
```

実行してみましょう。

```
Aクラスメソッド
Bクラスメソッド
Aクラスメソッド
Bクラスメソッド
```

継承してもメソッドの内容は変わっていませんが、**どのクラスから呼び出すか**によって、クラスメソッドが参照するクラス変数が変化しました。`cls`が**クラス自身**を参照していることがわかります。



***
[初学者のためのPython講座　オブジェクト指向編1　オブジェクト指向とは](https://qiita.com/kotakahe/items/9de3b515f8faf01510f0)
[初学者のためのPython講座　オブジェクト指向編2　クラスとインスタンス](https://qiita.com/kotakahe/items/3de8d471ea871b0a7024)
[初学者のためのPython講座　オブジェクト指向編3　メソッド](https://qiita.com/kotakahe/items/3360898ff84c2c141a1b)
[初学者のためのPython講座　オブジェクト指向編4　初期化メソッド](https://qiita.com/kotakahe/items/db3e9fa9d547bb6e9014)
[初学者のためのPython講座　オブジェクト指向編5　クラスの継承](https://qiita.com/kotakahe/items/b678250389af7fa885a5)
初学者のためのPython講座　オブジェクト指向編6　クラス変数とクラスメソッド
[初学者のためのPython講座　オブジェクト指向編7　カプセル化](https://qiita.com/kotakahe/items/2e17231868d78b35639f)

随時追加予定
次回「プロパティ」