インスタンス変数とクラス変数
- インスタンス変数 …
self.variable
の形で定義する - クラス変数 … クラスブロック直下に書かれた変数はクラス変数になる
class User(object): # クラス変数 name = 'User' def __init__(self, name): # インスタンス変数 self.name = name User.name # => User ichigo = User('Ichigo') ichigo.name # => Ichigo
クラス変数とインスタンス変数を同じ名前で作成してしまうと、一見するとインスタンスの初期化で name
を上書きしたように見えてしまう。
__class__
でインスタンスのクラスにアクセスできるようなので、これを使って name をみてみるとクラスブロック直下の name
がクラス変数だと理解できた。
ichigo = User('Ichigo') ichigo.name # => Ichigo print(ichigo.__class__) # => # => <class '__main__.User'> ichigo.__class__.name # => User User.name = 'Idol' ichigo.__class__.name # => Idol ichigo.name = Ichigo
同じ変数名でもクラス変数とインスタンス変数は別物として扱われている。
ただし、同じ名前の変数を作ってしまうとインスタンスからクラス変数を使いづらいので変数名は被らないようにしたほうが良さそう。
インスタンスメソッドとクラスメソッド
- インスタンスメソッド … クラスブロック内に通常に作成された関数。第一引数にインスタンス自身が渡される
- クラスメソッド … クラスブロック内に
@classmethod
デコレーター付きで作成された関数。第一引数にクラスが渡される
class User(object): name = 'User' def __init__(self, name, age=None): self.name = name self.age = age def hi(self): print(f'Hi, {self.name} ({self.age})') @classmethod def info(cls): print(f'This class is {cls.name}') # クラスメソッド User.info() # => This class is User ichigo = User('Ichigo', 16) # インスタンスメソッド ichigo.hi() # => Hi, Ichigo (16) # クラスメソッドはインスタンスからも呼び出せる ichigo.info() # => This class is User
クラスからもインスタンスメソッドが呼び出せるには呼び出せるっぽい
多分ダメな使い方と思うけど、第一引数にインスタンスを渡してあげるとエラーにならず実行できた…
ichigo = User('Ichigo', 16) User.hi(ichigo) # => Hi, Ichigo (16)
クラスメソットとスタティックメソッド
- クラスメソッド … 第一引数にクラス自身が渡される
- スタティックメソッド … クラス自身が渡されない
class User(object): name = 'User' @classmethod def info1(cls, message): # 第一引数でクラス自身が渡される print(f'{cls.name} {message}') @staticmethod def info2(message): # 純粋にメソッドに渡される引数だけが渡される print(f'{User.name} {message}') # クラスメソッド User.info1('info1') # => User info1 # インスタンスメソッド User.info2('info2') # => User info2 # User を継承したクラス class Idol(User): name = 'Idol' # 親クラスのクラスメソッドの cls は Idol クラスが渡されるようになる Idol.info1('Idol.info1') # => Idol Idol.info1 # スタティックメソッドは動的に渡される変数がないので出力は変わらない Idol.info2('Idol.info2') # => User Idol.info2
クラスメソッドの第一引数に渡されるクラスは継承されたクラスでは、継承されたクラス自身が渡されるので、ある意味動的とも言えるのかな。
所感
クラスブロック直下に置かれた変数がクラス変数になるのは、今まで通ってきた言語ではインスタンス変数になることが多かったのでチョットびっくりしました。
後はクラスからインススタンスメソッドが呼び出せたり、同じファイル内でクラス再定義できたり、Pythonって自由な言語なんだな〜という印象です。
[参考]
ジョゼ虎映画とても楽しみなのです。