
こんにちは、PyQサポートです。
今回は、クラスで利用される引数clsとselfの違いについて紹介します。
質問 クラスのメソッドの引数に指定されているclsとselfの違いを教えてください。
クラスのメソッドの引数に指定されている cls は self と何が違うのでしょうか?
データ属性クラスの第一引数がselfで、クラスメソッドの第一引数がclsでしょうか?
実際の実装
class TaxCalc: @classmethod def class_method(cls, price): assert cls.__name__ == TaxCalc.__name__ return int(price * 0.08) @staticmethod def static_method(price): return int(price * 0.08)
回答 selfはインスタンスメソッド、clsはクラスメソッドという違いがあります
selfとclsの違いについて、サンプルを通して説明します。
selfとは
- クラスに作成する通常のメソッドは、インスタンスメソッドとも呼ばれます。
- インスタンスメソッドの第1引数は
selfです(実際は任意ですが、慣習としてselfとします)。 selfはそのクラスの現在のインスタンスを表します。selfを介して、そのインスタンスの変数やメソッドにアクセスできます。selfはメソッド実行時に自動的に渡される引数です。
clsとは
@classmethodデコレータつけてメソッドを作成すると、クラスメソッドとなります。- クラスメソッドの第1引数は
clsです(実際は任意ですが、慣習としてclsとします)。 clsはそのクラス自身を表します。clsを介して、そのクラスのクラス変数やクラスメソッドにアクセスできます。clsはクラスメソッド実行時に自動的に渡される引数です。
サンプル
クラスとインスタンスの関係は、型(クラス)と実体(実体)です。
たとえると「たい焼きの型」(型)と「たい焼き」(実体)のようなものです。
クラスが「たい焼きの型」(cls)で、インスタンスが「たい焼き」(self)にあたります。
下記のサンプルを考えてみましょう。
class Taiyaki: maker = "鈴木屋" def __init__(self, content): self.content = content def say_azi(self): print(f"中身は{self.content}です") @classmethod def say_maker(cls): print(f"{cls.maker}のたい焼きです") @classmethod @staticmethod def describe(): print("これはたい焼き用のクラスです")
このTaiyakiクラスを使って粒あんとカスタードクリームのたい焼きを作ってみます。
>>> t_ann = Taiyaki("粒あん")
>>> t_custard = Taiyaki("カスタードクリーム")
say_azi()は通常のメソッド(インスタンスメソッド)で、selfはそれぞれのインスタンス(たい焼き)です。
そのため、self.contentにはそれぞれのインスタンスの値が設定されています。
>>> t_ann.say_azi() 中身は粒あんです >>> t_custard.say_azi() 中身はカスタードクリームです
say_maker()はクラスメソッドで、clsはクラスそのもの(Taiyakiクラス自身)です。
そのため、t_annであってもt_custardであっても、cls.makerには同じ値が設定されています。
>>> t_ann.say_maker() 鈴木屋のたい焼きです >>> t_custard.say_maker() 鈴木屋のたい焼きです
さらに、クラスメソッドはクラス自身にひも付くので、インスタンスを作らずにTaiyakiクラスから直接実行することもできます。
>>> Taiyaki.say_maker() 鈴木屋のたい焼きです
ちなみに、say_azi()メソッドはTaiyakiクラスのインスタンスにひも付くので、Taiyakiクラスから直接実行することはできません。
>>> Taiyaki.say_azi() Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: say_azi() missing 1 required positional argument: 'self'
関連:スタティックメソッド
また、関連してdescribe()のように@staticmethodデコレータをつけてメソッドを作成すると、スタティックメソッドになります。
これは通常の関数をクラスの中に定義する方法です。
通常の関数と同じなので、第1引数にselfやclsといった自動的に渡される引数はありません。
スタティックメソッドは、「クラスの中に書きたいけどインスタンスやクラスの情報は特に必要ない関数」を書く場合に利用できます。
使い方は前述のクラスメソッドのように、インスタンスから実行することもできますし、クラスから実行することもできます。
>>> t_ann.describe() これはたい焼き用のクラスです >>> t_custard.describe() これはたい焼き用のクラスです >>> Taiyaki.describe() これはたい焼き用のクラスです
まとめ
まとめると以下のようになります。
- self
- クラスから作成されたインスタンス
- それぞれのインスタンス固有のインスタンス変数にアクセスできる
- cls
- クラス自身
- それぞれのインスタンス間で共通のクラス変数にアクセスできる