Pythonの型と二つのクラス、そしてインスタンス
Python Hack-a-thon 2011.02 のLTで使う資料を書いていてふと思い出したのが、Pythonでは厳密に言えば「クラスから生成したオブジェクト」を一言で表現する用語が無いのでめんどくさい、という話である。
C++などでは「インスタンス」と言ってしまえばお仕舞いなのだが、Pythonでは「インスタンス」には別の意味があるのでややこしい。クラス定義から作ったオブジェクトであっても、インスタンスだったりインスタンスじゃなかったりするのだ。
オブジェクトの「型」
まず、Pythonでの「型」について考えてみよう。Pythonでは、全てのオブジェクトは「型」を持っている。オブジェクトの「型」は type() で確認することができる。
>>> type(100) <type 'int'> >>> import sys >>> type(sys) <type 'module'>
数字はint、モジュールはmoduleという型のオブジェクトだ。「型」もまたオブジェクトであるので型を持っている。
>>> type(int) <type 'type'>
全ての型は、type という型のオブジェクトなのである。
一つ目のクラス
Pythonの「クラス」とはなんだろうか?C++ではクラスは「ユーザ定義型」と呼ばれ、型の一種である。
Pythonでは、「クラス」は型だったり型ではなかったりする。Python2で、こんなクラス定義があったとする。
>>> class Spam: ... pass ...
見てわかるとおり、Spamというクラスを定義している。さて、このSpamというのは何者だろうか?
>>> type(Spam) <type 'classobj'>
Spamは、classobjという型のオブジェクトだ。つまり、Spamクラスはtype型ではないので、「型」ではないのである。
>>> isinstance(Spam, type) False
インスタンス
ここで、Spamクラスからオブジェクトを生成しよう。
>>> spamobj = Spam() >>> spamobj <__main__.Spam instance at 0x0283D3A0> >>> type(spamobj ) <type 'instance'>
Spamクラスから、spamobjというオブジェクトを作った訳だが、Spamクラスは型ではないのでspamobjオブジェクトの型は当然「Spam」ではあり得ない。 クラスから生成されたオブジェクトは全て「instance」という型のオブジェクトとなるのである。
言い方を変えれば、インスタンスとはクラスから生成されたオブジェクト、ということになる。ん?だったら冒頭で
「クラスから生成したオブジェクト」を一言で表現する用語が無い
と書いたのはなんだんだ?
もう一つのクラス
さて、もう一つクラスを定義してみよう。
>>> class NewStyleSpam(object): ... pass ...
今度は NewStyleSpam というクラスだ。Spamとの違いは、object型を継承している、という点のみだ。NewStyleSpamはどんなオブジェクトだろうか?
>>> type(NewStyleSpam) <type 'type'>
先ほどのSpamクラスはclassobj型のオブジェクトだったが、NewStyleSpamクラスはtype型のオブジェクトだ。つまり、Spamクラスは型ではないが、NewStyleSpamクラスは型なのである。
つまり、NewStyleSpamのように、「型」を継承するクラスは、型となるのである。このように型から継承したクラスのことを、「新スタイルクラス(new style class)」と呼ぶ。
新スタイルクラスは「インスタンス」を生成しない
新スタイルクラスからオブジェクトを生成してみよう。
>>> newstylespamobj = NewStyleSpam() >>> type(newstylespamobj) <class '__main__.NewStyleSpam'>
Spamクラスから生成したオブジェクトは、instance型のオブジェクトであった。しかし、NewStyleSpamは型であるので、ここで生成したオブジェクトはNewStyleSpam型のオブジェクトである。Spamクラスはインスタンスを生成するが、NewStyleSpamが生成するのはNewStyleSpam型のオブジェクトであり、「インスタンス」型ではないのである。
通常はクラスから生成したオブジェクトを「インスタンス」と呼んでしまって問題ないのだが、厳密には新スタイルクラスは「インスタンス」を生成しない。実装上の細かい話をしている時には、この違いを意識してないと「?」となってしまうことがあるので、一応覚えておくと良いだろう。
Python3では
実は、ここまではPython2までの話だ。Python3では、Python2の「旧スタイルクラス」が存在せず、全て「新スタイルクラス」となる。
>>> class Spam: ... pass ... >>> Spam <class '__main__.Spam'> >>> type(Spam) <class 'type'> >>> type(Spam()) <class '__main__.Spam'>
classobj型やinstance型というのは使われていない。従って、Python3の世界は、クラスから生成したオブジェクトを「インスタンス」と言ってもなんら問題のないパラダイスなのである。