如何引用父类的子类的任何对象'在Python类型注释?
示例:FooBase
是一个抽象基类,Foo1
,Foo2
等是子类的子类。我希望函数接受FooBase
的任何后代。这样做:
def do_something(self, bar:FooBase):
pass
或者这只会接受类FooBase
的对象,鉴于FooBase
是抽象的,这当然是不可能的?在这种情况下,我是否需要构建Union
所有案例(请上帝,我希望不是!),还是我可以通过其他方式抽象地表达这种关系?
答案 0 :(得分:2)
继承也适用于带注释的类型。作为Foo
子类型的FooBase
的任何实例也是类型FooBase
的有效对象。因此,您可以将FooBase
对象以及Foo
对象传递给函数。
如果您想将该功能仅限于FooBar
的子类,您可以查看Type[C]
构造:The type of class objects。
答案 1 :(得分:2)
使用 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())
答案 2 :(得分:0)
这只会接受类
FooBase
的对象吗?
不,这也会接受任何子类。这在类型提示PEP理论中也有说明,特别是summary of Gradual Typing section:
如果
t1
是t2
的子类型,则t1
类型与类型t2
一致。 (但不是相反。)
在处理类型提示时,请查看它以获取更多指示。
我是否需要建立所有案例的联盟。
即使你这样做了,也会从Union
中删除所有子类,并且会跳过子类。尝试创建您提到的Union
:
typing.Union[Foo1, Foo2, FooBar]
,结果应为FooBar
。它是一个抽象类的事实在这里没有任何区别,Python本身在typing
模块中使用了许多抽象类。
以Sized
abc为例;使用Sized
提示函数允许替换任何虚拟子类(定义{{1}}的类):
__len__