68

注释需要类对象而不是该类实例的函数参数的正确方法是什么?

在下面的示例中,some_classargument 应该是一个类型实例(它是一个类),但这里的问题是它type太宽泛了:

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

some_class需要一组特定类型对象的情况下,使用type根本没有帮助。该typing模块可能需要一个类泛型来执行此操作:

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

在上面的示例中,是some_class或类,而不是它的实例。它们在类树中的位置应该无关紧要,因为它也应该是一个有效的案例。所以,FooBarFazsome_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()

对 mypy、pytype、PyCharm 等应该没问题。

如何使用当前的实现(Python 3.6 或更早版本)来做到这一点?

4

1 回答 1

85

要注释作为类的对象,请使用typing.Type. 例如,这将告诉类型检查器some_class是类Foo还是它的任何子类:

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

注意Type[Union[Foo, Bar, Baz]]Union[Type[Foo], Type[Bar], Type[Baz]]是完全等价的。

如果some_class可以是多个类中的任何一个,您可能希望它们都继承自同一个基类,并使用Type[BaseClass]. 请注意,现在继承必须是非虚拟的(mypy 对虚拟继承的支持正在讨论中)。

编辑以确认这Type[Union[...是允许的。

于 2017-04-17T19:02:58.387 回答