Python クラス #5

株式会社リュディアです。今回も引き続きクラスについてまとめていきます。

前回までの Python クラスについてのまとめへのリンクは以下を参考にしてください。

今回からメソッドについてまとめます。最初にメソッドと関数の違いについて記載しておきます。まず形式的な違いはクラス内で宣言、定義されている関数をメソッドと呼び、クラス外で宣言、定義されている関数は単に関数と呼びます。次に動作の観点から考えます。クラス内で宣言、定義されている関数、つまりメソッドはあるオブジェクトに対する操作を定義していることがほとんどです。

今回は Python の 3 つのメソッドのうち、クラスメソッドについてまとめてみます。先にまとめた変数でもクラス変数とインスタンス変数の区別がありましたね。同じように考えてもらえば問題ないです。さっそく例を見てみましょう。

class VegetableClass():
    __num_of_types = 800
    def __init__(self, c):
       self.__color = c

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(VegetableClass.num_of_types())
print(lettuce.color())
print(tomato.color())

# ---------------------------------------------------------------------------
# AttributeError                            Traceback (most recent call last)
# <ipython-input-39-e9d1d435052e> in <module>
#       7 tomato = VegetableClass('red')
#       8 
# ----> 9 print(VegetableClass.num_of_types())
#      10 print(lettuce.color())
#      11 print(tomato.color())
# 
# AttributeError: type object 'VegetableClass' has no attribute 'num_of_types'

今回、クラス変数 __num_of_types、インスタンス変数 __color ともにアンダースコアをつけているのでクラス外非公開となりprint文で表示しようとしてエラーが出ている状態です。ではまずクラスメソッドを追加してクラス変数をクラス外から覗けるようにしてみましょう。

class VegetableClass():
    __num_of_types = 800
    def __init__(self, c):
       self.__color = c
    @classmethod
    def num_of_types(cls):
       print('Called class method')
       return cls.__num_of_types

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(VegetableClass.num_of_types())

# Called class method
# 800

クラスメソッド num_of_types(cls) を追加しました。クラスメソッドの書き方と使い方を箇条書きにしてみます。

1. @classmethod でデコレート
2. 第1引数は必ず cls としクラス自身を表現する
3. クラス変数を return する場合は引数の cls を利用して return cls.変数名とする
4. 利用する際にインスタンスは不要でクラス名.クラスメソッドの形式で呼び出し、引数の cls に相当する部分は不要

どうでしょうか。これでクラスメソッドを通してクラス変数 __num_of_types を表示できていることがわかりましたね。またインスタンスを使ってのアクセスではなくクラス名を使ってアクセスしていることも理解してください。ただし前にまとめたクラス変数との違いはクラスメソッドはインスタンスから呼び出しても問題ないことです。インスタンスは不要でクラス名で呼び出すことが可能ですが、インスタンスから呼び出してもよい、という規則です。ここがクラス変数とクラスメソッドの違いです。クラス変数はインスタンスからアクセスすると明確な問題がありましたね。実際 lettuce インスタンスからクラスメソッド num_of_types() を呼び出している以下の例を見ても問題ないことがわかりますね。

class VegetableClass():
    __num_of_types = 800
    def __init__(self, c):
       self.__color = c
    @classmethod
    def num_of_types(cls):
       print('Called class method')
       return cls.__num_of_types

lettuce = VegetableClass('green')
tomato = VegetableClass('red')

print(lettuce.num_of_types())

# Called class method
# 800

ただ私はプログラミングでクラス変数、クラスメソッドはクラス名から呼び出すように習慣づけています。このあたりは人の好みだと思います。

Python のクラスに関するまとめの続きは以下からどうぞ。

では、ごきげんよう。



この記事が気に入ったらサポートをしてみませんか?