Python 3 类型注释和子类

新手上路,请多包涵

如何在 Python 类型注释中引用“任何子类化父类的对象”?

示例: FooBase 是一个抽象基类,其中 Foo1Foo2 等是子类。我希望函数接受 FooBase 的任何后代。这会做:

 def do_something(self, bar:FooBase):
    pass

或者这只会接受类 FooBase 的对象,这当然是不可能的,因为 FooBase 是抽象的?在那种情况下,我是否需要构建所有情况的 Union (求求上帝,我希望不要!),或者我可以通过其他方式抽象地表达这种关系吗?

原文由 Chris vCB 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

这将只接受类 FooBase 的对象吗?

不,这也将接受任何子类。这在 Theory of Type Hinting PEP 中也有说明,特别 是 Gradual Typing 部分的摘要

A type t1 is consistent with a type t2 if t1 is a subtype of t2 . (但反之则不然。)

在处理类型提示时,请查看它以获取更多指示。

我需要建立一个所有案例的联盟吗?

即使您这样做了,所有子类都将从 Union 中消除,并且子类将被跳过。尝试创建 Union 你提到:

 typing.Union[Foo1, Foo2, FooBar]

结果应该是 FooBar 。它是一个抽象类的事实在这里没有区别,Python 本身在 typing 模块中使用了许多抽象类。

Sized abc 为例;使用 Sized 暗示函数允许替换任何虚拟子类(定义 __len__ 的类):

 def foo(obj: Sized): pass

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

原文由 Dimitris Fasarakis Hilliard 发布,翻译遵循 CC BY-SA 3.0 许可协议

继承也适用于带注释的类型。 Foo 的子类型,也是 FooBase FooBase 的有效对象。因此,您可以将 FooBase 对象以及 Foo 对象传递给函数。

如果您想将函数限制为 FooBar 的 _子类_,您可以查看 Type[C] 构造: 类对象的类型

原文由 poke 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题