简体   繁体   English

Python 3 类型注解和子类

[英]Python 3 type annotations and subclasses

How do I refer to 'any object that subclasses a parent class' in Python type annotations?如何在 Python 类型注释中引用“任何子类化父类的对象”?

Example: FooBase is an abstract base class, from which Foo1 , Foo2 , etc. are subclassed.示例: FooBase是一个抽象基类,从它Foo1Foo2等。 I want the function to accept any descendant of FooBase .我希望该函数接受FooBase任何后代。 Will this do:这会不会:

def do_something(self, bar:FooBase):
    pass

Or will this only accept an object of class FooBase , which of course is impossible given that FooBase is abstract?或者这只会接受FooBase类的对象,鉴于FooBase是抽象的,这当然是不可能的? In that case, do I need to build a Union of all cases (please God I hope not!), or can I through some other way express this relationship abstractly?在这种情况下,我是否需要建立一个所有案例的Union (拜托上帝,我希望不是!),或者我可以通过其他方式抽象地表达这种关系吗?

Inheritance also applies to annotated types.继承也适用于带注释的类型。 Any instance of Foo which is a subtype of FooBase is also a valid object of the type FooBase .的任何实例Foo其的子类型FooBase也是类型的有效对象FooBase So you can pass a FooBase object but also a Foo object to the function.因此,您可以将FooBase对象和Foo对象传递给函数。

If you want to limit the function to only subclasses of FooBar , you could take a look at the Type[C] construct: The type of class objects .如果您想将该功能限制为仅FooBar子类,您可以查看Type[C]构造: 类对象的类型

will this only accept an object of class FooBase ?这将只接受FooBase类的对象吗?

No, this will accept any subclasses too.不,这也将接受任何子类。 This is also stated in the Theory of Type Hinting PEP, specifically the summary of Gradual Typing section :这也在 Theory of Type Hinting PEP 中有所说明,特别是 Gradual Typing 部分总结

A type t1 is consistent with a type t2 if t1 is a subtype of t2 .如果t1t2的子类型,则类型t1与类型t2一致。 (But not the other way around.) (但反过来不行。)

take a look at it for further pointers when dealing with type hints.在处理类型提示时,请查看它以获取更多指针。

do I need to build a Union of all cases.我是否需要建立一个所有案例的联盟。

Even if you did, all subclasses will be eliminated from the Union and the subclasses are going to get skipped.即使你这样做了,所有的子类都将从Union删除,子类将被跳过。 Try creating the Union you mention:尝试创建您提到的Union

typing.Union[Foo1, Foo2, FooBar]

and the result should be FooBar .结果应该是FooBar The fact that it is an abstract class pays no difference here, Python itself uses many abstract classes in the typing module.它是一个抽象类的事实在这里没有区别,Python 本身在typing模块中使用了许多抽象类。

Take for example the Sized abc;Sized abc 为例; hinting a function with Sized allows any virtual subclass (classes defining __len__ ) to be substituted:使用Sized提示函数允许替换任何虚拟子类(定义__len__类):

def foo(obj: Sized): pass

foo([1, 2, 3, 4]) # ok
foo([2, 3, 4, 5]) # ok

Solved using TypeVar and PyCharm checker accepts it:使用TypeVar解决,PyCharm 检查器接受它:

from pydantic import BaseModel
class MyModel(BaseModel):
    pass


from typing import TypeVar
BaseModelType = TypeVar('BaseModelType', bound='BaseModel')

async def do_smth(value: BaseModelType):
    pass

# ...

await do_smth(MyModel())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM