如何注释类对象的类型(而不是类实例) ?

什么是正确的方法来注释一个函数参数,期望一个类对象,而不是该类的实例?

在下面的例子中,some_class参数应该是一个类型实例(这是一个类) ,但是这里的问题是 type太宽了:

def construct(some_class: type, related_data:Dict[str, Any]) -> Any:
...

some_class需要一组特定类型对象的情况下,使用 type毫无帮助。typing模块可能需要一个 Class 泛型来完成以下工作:

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

在上面的示例中,some_classFooBarFaz类,而不是它的实例。它们在类树中的位置无关紧要,因为 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()

应该是可以的,我的密码,Pytype,PyCharm 等。

如何使用当前的实现(Python 3.6或更早的版本)完成这项工作?

38777 次浏览

To annotate an object that is a class, use typing.Type. For example, this would tell the type checker that some_class is class Foo or any of its subclasses:

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

Note that Type[Union[Foo, Bar, Baz]] and Union[Type[Foo], Type[Bar], Type[Baz]] are completely equivalent.

If some_class could be any of a number of classes, you may want to make them all inherit from the same base class, and use Type[BaseClass]. Note that the inheritance must be non-virtual for now (mypy support for virtual inheritance is being discussed).

Edited to confirm that Type[Union[... is allowed.