Python 3.6では機能し、Python 3.8では失敗するコードがあります。次のように要約するとsuper
、のサブクラスを呼び出すtyping.NamedTuple
ようになります。
<ipython-input-2-fea20b0178f3> in <module>
----> 1 class Test(typing.NamedTuple):
2 a: int
3 b: float
4 def __repr__(self):
5 return super(object, self).__repr__()
RuntimeError: __class__ not set defining 'Test' as <class '__main__.Test'>. Was __classcell__ propagated to type.__new__?
In [3]: class Test(typing.NamedTuple):
...: a: int
...: b: float
...: #def __repr__(self):
...: # return super(object, self).__repr__()
...:
>>> # works
このsuper(object, self).__repr__
呼び出しの目的は'<__main__.Test object at 0x7fa109953cf8>'
__repr__
、タプル要素のすべてのコンテンツを出力する代わりに標準を使用することです(デフォルトで発生します)。同様のエラーが発生することについていくつかの 質問がありますがsuper
、それらは:
- パラメータなしバージョンを参照してください
super()
- Python 3.6で失敗しました(3.6-> 3.8アップグレードの前に動作しました)
- 私が制御しているカスタムメタクラスではなく、stdlibが提供するものであることを考えると、どうしてもこれを修正する方法を理解できません
typing.NamedTuple
。
私の質問は、Python 3.6との下位互換性を維持しながらこれを修正するにはどうすればよいですか(それ以外の場合は@dataclasses.dataclass
、から継承する代わりに使用するだけtyping.NamedTuple
です)?
副次的な問題は、問題のある呼び出しがまだ実行されていないメソッド内にある場合、定義時にこれがどのように失敗するかsuper
です。例えば:
In [3]: class Test(typing.NamedTuple):
...: a: int
...: b: float
...: def __repr__(self):
...: return foo
が未定義の参照で__repr__
あっても、(実際にを呼び出すまで)機能しfoo
ます。であるsuper
という点で魔法?
__repr__ = object.__repr__
クラス定義での使用は、Python3.6とPython3.8で動作します
typing.NamedTuple
です。typing.NamedTupleMeta
、それはいくつかの厄介なことをしています。どうやら、コンパイル時には利用可能であるsuper()
必要__class__
がありますが、ここではそうではありません。参照:Python 3.6メタクラスの例を提供__classcell__
super
と、Test
インスタンスの表現ではなく、オブジェクト自体の表現が表示されます。