2017-01-01 16 views
2

クラスのインスタンスではなくクラスオブジェクトが必要な関数の引数にアノテーションを付ける適切な方法は何ですか?(クラスインスタンスではなく)型インスタンスに注釈を付けるにはどうすればよいですか?

以下の例では、some_class引数は(WICHがクラスである)型のインスタンスであると予想されるが、ここでの問題はtypeが広すぎるということである:

some_classがA期待場合
def construct(some_class: type, related_data:Dict[str, Any]) -> Any: 
    ... 

タイプオブジェクトの特定のセットは、typeを使用してまったく助けません。 typingモジュールは、これを行い、一般的なクラスを必要としているかもしれない:上記の例で

def construct(some_class: Class[Union[Foo, Bar, Baz]], related_data:Dict[str, Any]) -> Union[Foo, Bar, Baz]: 
    ... 

は、 some_classFooBarまたは Fazクラスではなく、それのインスタンスです。 some_class: Class[Foo]も有効なケースである必要があるため、クラスツリー内の位置は関係ありません。したがって、

# classes are callable, so it is OK 
inst = some_class(**related_data) 

または

# instances does not have __name__ 
clsname = some_class.__name__ 

または

# an operation that only Foo, Bar and Baz can perform. 
some_class.a_common_classmethod() 

は、PyCharmをpytypeをmypyためにOKであるべき、など

これは、(現在の実装で行うことができますどのようにPython 3.6以前)?

+0

'type'より具体的にする必要がある場合は、メタクラスまたは抽象基底クラスを導入してください。 – jonrsharpe

+0

@jonrsharpe - メタクラスがこのトリックを行うとは思うが、まだPythonではこのレベルに達していない。 3.6で変数アノテーション(クラス変数とインスタンス変数を異ならせる 'ClassVar'を含む)が導入されたので、クラスインスタンスに注釈を付ける方法がたくさんある場合、' type'を使ってクラスオブジェクトに注釈を付ける必要があります。多分私は将来の更新やレシピを待たなければならないでしょう:)。 –

+0

'typing.Type'に依存し、' Foo = TypeVar ['Foo'、bond = Bar] 'のようにする必要があります。ここで' Bar'はABCです。 def構造体(some_class:Type [Foo]、...) - > Foo'である。私は特に 'TypeVar'を使う必要はありませんが、それは唯一の方法だと思われます... –

答えて

2

クラスであるオブジェクトに注釈を付けるには、typing.Typeを使用します。 Type[Union[Foo, Bar, Baz]]Union[Type[Foo], Type[Bar], Type[Baz]]が完全に等価であること

from typing import Type 
class Foo: ... 
class Bar(Foo): ... 
class Baz: ... 
some_class: Type[Foo] 
some_class = Foo # ok 
some_class = Bar # ok 
some_class = Baz # error 
some_class = Foo() # error 

注:例えば、これは、some_classクラスFooまたはそのサブクラスのいずれかであること型チェッカーを言うだろう。

some_classが複数のクラスのいずれかである場合は、それらがすべて同じ基本クラスから継承され、Type[BaseClass]を使用することができます。継承は今は非仮想でなければならないことに注意してください(仮想継承のためのmypyサポートはbeing discussedです)。

Type[Union[...が許可されていることを確認して編集しました。

関連する問題