mypyドキュメントによれば、クラスが自身を参照する必要がある場合は、forward-referenceを使用できます。mypyのNamedTupleから継承したクラスのメソッドの型チェックを実装するにはどうすればよいですか?
これは通常のクラスではうまくいくようですが、NamedTupleから継承したクラスではうまく動作しません。
"""
All this code runs without error on Python 3.6
The question is why the 'B' class' __add__ method
raises an error through mypy.
"""
from typing import *
class A:
def __init__(self, x: int) -> None:
self.x = x
def __add__(self, other: 'A') -> 'A':
return type(self)(self.x + other.x)
def __str__(self) -> str:
return f'A(x={self.x})'
A1 = A(1)
A2 = A(2)
A3 = A1 + A2
print(A3)
class B(NamedTuple('B', [('x', int)])):
# The following line will raise an error in mypy
# error: Argument 1 of "__add__" incompatible with supertype "tuple"
def __add__(self, other: 'B') -> 'B':
return type(self)(self.x + other.x)
B1 = B(1)
B2 = B(2)
B3 = B1 + B2
print(B3)
更新:Guido van Rossum自身が以後回答していますthis question on Github。
あなたが達成しようとしていることを100%確信しているわけではありませんが、最初の例に基づいて、クラスBに対して+を再定義して、 B. mypyがデフォルトでこれをサポートしていない理由は、「Liskov置換原則」と呼ばれるものです(説明のためGoogleにそれを伝えることができます)。
回避策があります:put#type:エラーを生成する行を無視します(def には行を追加します)。これは健全ではありませんが、Bインスタンスをタプルとみなしてタプル連結を試みるコードに決して渡すことができない限り、必要な処理を行います。
これは奇妙です。 'class B'は既に' __name__' 'B'を持つクラスから継承していることに注意してください...多分それは物事を混乱させるでしょう。だから '__mro__'は'(、 __main __。B '>、、) ' –
のようになります。 'B'の名前、または' namedtuple'に渡す名前です。クラスB(NamedTuple( 'SuperB'、[( 'x'、int)]))): ' –
これは関連するかもしれません:https://github.com/python/mypy/issues/1237 –