こんにちは、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
- クラス自身
- それぞれのインスタンス間で共通のクラス変数にアクセスできる