次のように使用するとsuper()
TypeError が発生します。なぜでしょうか?
>>> from HTMLParser import HTMLParser
>>> class TextParser(HTMLParser):
... def __init__(self):
... super(TextParser, self).__init__()
... self.all_data = []
...
>>> TextParser()
(...)
TypeError: must be type, not classobj
StackOverflow にも同様の質問があります:Python super() は TypeError を発生させます、このエラーは、ユーザー クラスが新しいスタイルのクラスではないという事実によって説明されます。ただし、上記のクラスは から継承しているため、新しいスタイルのクラスですobject
。
>>> isinstance(HTMLParser(), object)
True
何が足りないのでしょうか?super()
ここで をどのように使用すればよいのでしょうか?
HTMLParser.__init__(self)
の代わりにを使用するとsuper(TextParser, self).__init__()
動作しますが、TypeError を理解したいと思います。
PS: Joachim は、新しいスタイルのクラス インスタンスであることは、 であることと同じではないと指摘しましたobject
。私はその逆を何度も読んだので、混乱しました (インスタンス テストに基づく新しいスタイルのクラス インスタンス テストの例object
:https://stackoverflow.com/revisions/2655651/3)。
ベストアンサー1
そうですね、いつもの「super()
旧式のクラスでは使用できません」ですね。
しかし、重要な点は、「これは新しいスタイルのインスタンス(つまりオブジェクト)ですか?」という正しいテストは
>>> class OldStyle: pass
>>> instance = OldStyle()
>>> issubclass(instance.__class__, object)
False
そして(質問のように)そうではありません:
>>> isinstance(instance, object)
True
クラスの場合、「これは新しいスタイルのクラスであるかどうか」の正しいテストは次のとおりです。
>>> issubclass(OldStyle, object) # OldStyle is not a new-style class
False
>>> issubclass(int, object) # int is a new-style class
True
重要な点は、旧スタイルのクラスでは、インスタンスのクラスとその型が異なるということです。ここで、OldStyle().__class__
は でOldStyle
、 を継承しませんobject
が、type(OldStyle())
はinstance
型で、を継承します。object
基本的に、旧スタイルのクラスは 型のオブジェクトを作成するだけですinstance
(一方、新スタイルのクラスは、そのクラス自体の型のオブジェクトを作成します)。おそらくこれが、インスタンスOldStyle()
がである理由ですobject
。インスタンスはtype()
を継承します(そのクラスがを継承しないobject
という事実は考慮されません。旧スタイルのクラスは 型の新しいオブジェクトを作成するだけです)。部分的な参照:object
instance
https://stackoverflow.com/a/9699961/42973。
PS: 新しいスタイルのクラスと古いスタイルのクラスの違いは、次の例でも確認できます。
>>> type(OldStyle) # OldStyle creates objects but is not itself a type
classobj
>>> isinstance(OldStyle, type)
False
>>> type(int) # A new-style class is a type
type
(旧スタイルのクラスは型ではないため、インスタンスの型にすることはできません)。