今さらPython3 (41) - クラスの続き

第6章も後半に差し掛かってきました。

入門 Python 3

入門 Python 3

メソッドのタイプ

オブジェクトを習いたての時は、インスタンス化ってコンセプトを理解するのが少し難しかったりするけど、メソッドの場合もインスタンス化された先でそれぞれ使用されるのがインスタンスメソッドインスタンス化されないで、同じクラスを参照しているすべてのインスタンスに影響を与えるクラスをクラスメソッドと呼ぶ。

Python2のときは、なんだかうやむやにされていたけど、Python3では@classmethodというデコレータを使うんですね。

>>> class A():
...     count = 0
...     def __init__(self):
...         A.count += 1
...     def exclaim(self):
...         print("I'm an A!")
...     @classmethod
...     def kids(cls):
...         print("A has", cls.count, "little objects.")
... 
>>> easy_a = A()
>>> breezy_a = A()
>>> wheezy_a = A()
>>> A.kids()
A has 3 little objects.

これまでと違うところを探すと、__init__()の中で、self.countとなりそうなところがA.countになってる。selfになるとインスタンスごとに個別に数えちゃうので、俺はクラス属性だぞと主張している訳だね。@classmethodはお約束のデコレータで、第1引数はclsを使うのが慣例でクラス自体を指している。A.countとkids()の中にあるcls.countは同じものを指していると理解すればOK。

ちなみに、、、

>>> class A_dash():
...     count = 0
...     def __init__(self):
...         count += 1
...     @classmethod
...     def kids(cls):
...         print("A_dash has", cls.count, "little objects.")
... 
>>> b = A_dash()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in __init__
UnboundLocalError: local variable 'count' referenced before assignment
>>> 

__init__の中にあるcountをわざわざA.countとやらないとダメなの?という確認をしたのが上のやつ。結論から言うと怒られました。よく見直すとclass A_dash(Aも同じ)の一番外側にcountというクラス内で有効なローカル変数(と言いつつ、これがクラス属性)が定義されていて、そのcount関数を足し上げているので、明示的にA.countと言わないとダメなんだろうね。

>>> class CoyoteWeapon():
...     @staticmethod
...     def commercial():
...          print("This CoyoteWepon has been brought to you by Acme")
... 
>>> CoyoteWeapon.commercial()
This CoyoteWepon has been brought to you by Acme
>>> 

これが静的メソッド。オブジェクトを作らず(=インスタンス化せずに?)実行できるというのが他との違いだそうで。

(つづく)