初期化のためのヘルパーメソッドを持つクラスが与えられた場合:
class TrivialClass:
def __init__(self, str_arg: str):
self.string_attribute = str_arg
@classmethod
def from_int(cls, int_arg: int) -> ?:
str_arg = str(int_arg)
return cls(str_arg)
from_int
メソッドの戻り値の型に注釈を付けることは可能ですか?
cls
とTrivialClass
の両方を試しましたが、PyCharmはそれらを未解決の参照としてフラグ付けし、その時点で妥当と思われます。
generic typeを使用して、cls
のインスタンスを返すことを示します。
_from typing import Type, TypeVar
T = TypeVar('T', bound='TrivialClass')
class TrivialClass:
# ...
@classmethod
def from_int(cls: Type[T], int_arg: int) -> T:
# ...
return cls(...)
_
クラスメソッドをオーバーライドした後、親クラス(TrivialClass
またはまだ祖先であるサブクラス)のインスタンスを返すサブクラスは、ファクトリメソッドはcls
タイプのインスタンスを返すように定義されているため、エラーとして検出されます。
bound
引数は、T
がTrivialClass
(のサブクラス)でなければならないことを指定します。ジェネリックを定義するときにクラスがまだ存在しないため、 forwardreference (文字列名前)。
PEP 484の インスタンスおよびクラスメソッドへの注釈セクション を参照してください。
注:この回答の最初の改訂では、クラス自体を戻り値として指定する前方参照を使用することを提唱しましたが、 issue 1212 により、代わりにジェネリックを使用できるようになり、より良い解決策になりました。
Python 3.8以降、モジュールを-で開始するときに、アノテーションで前方参照を使用する必要がなくなりますできます。 _from __future__ import annotations
_ ですが、モジュールレベルでTypeVar()
オブジェクトを作成することは注釈ではありません。
戻り値の型に注釈を付ける簡単な方法は、クラスメソッドの戻り値の注釈として文字列を使用することです。
# test.py
class TrivialClass:
def __init__(self, str_arg: str) -> None:
self.string_attribute = str_arg
@classmethod
def from_int(cls, int_arg: int) -> 'TrivialClass':
str_arg = str(int_arg)
return cls(str_arg)
これはmypy0.560を渡し、Pythonからのエラーはありません。
$ mypy test.py --disallow-untyped-defs --disallow-untyped-calls
$ python test.py
Python 3.7から __future__.annotations
:
from __future__ import annotations
class TrivialClass:
# ...
@classmethod
def from_int(cls, int_arg: int) -> TrivialClass:
# ...
return cls(...)
編集:classmethodをオーバーライドせずにTrivialClass
をサブクラス化することはできませんが、これが必要ない場合は、前方参照よりも優れていると思います。