38

初期化用のヘルパー メソッドを持つクラスがあるとします。

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はそれらを未解決の参照としてフラグを立てます。これはその時点で妥当に聞こえます。

4

4 に答える 4

75

ジェネリック型を使用して、次のインスタンスを返すことを示します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。ジェネリックを定義するとき、クラスはまだ存在しないため、前方参照(名前付きの文字列) を使用する必要があります。

PEP 484 のインスタンスとクラスメソッドに注釈を付けるセクションを参照してください。


注:この回答の最初の改訂では、クラス自体を戻り値として指定する前方参照を使用することを提唱しましたが、問題 1212により、代わりにジェネリックを使用できるようになり、より良い解決策になりました。

Python 3.7 では、モジュールを で開始するときにアノテーションで前方参照を使用する必要なくなりますが、モジュール レベルでオブジェクトをfrom __future__ import annotations作成することはアノテーションではありません。TypeVar()これは Python 3.10 でも当てはまり、アノテーションのすべての型ヒントの解決が延期されます。

于 2016-08-29T11:49:14.813 に答える
0

Python 3.11 では、新しいSelf型を使用してこれを行うより良い方法があります。

class TrivialClass:
    def __init__(self, str_arg: str):
        self.string_attribute = str_arg

    @classmethod
    def from_int(cls, int_arg: int) -> Self:
        str_arg = str(int_arg)
        return cls(str_arg)

これはサブクラスでも機能します。

これはPEP 673で説明されています。クラスメソッド署名での使用のセクションで使用されている例は、この質問とまったく同じです。

Python 3.11 がリリースされたら (2022-10-03 現在)、この回答を受け入れる予定です。

于 2022-02-09T11:11:45.973 に答える