是否可以只在类对象中键入hint,但不包括子类对象



我想专门为特定类键入hint参数,但排除任何子类。

class A:
pass
class B(A):
pass
def foo(obj: A):
pass
foo(B()) # I'd like the type checker to warn me here that it expects A, not B

这可能吗?如果是,怎么做?

(如果你能告诉我我会怎么称呼它,那就加分。谷歌搜索没有帮助,但恐怕我用错了术语来描述它(

不,这是不可能的。

从根本上讲,Python类型生态系统假设您遵循Liskov替换原则——假设在设计用于处理父类的地方替换子类总是安全的。

事实上,它允许您在代码片段中除了传递A的实例之外,还传递B的实例,这只是这一原则的一个例子。

因此,如果你的子类B被设计成而不是遵循Liskov替换原则,那么它可能一开始就不是真正的"一种"a,也不应该将其子类化。

你可以通过调整你的代码使B正确地遵循Liskov,或者让B停止子类化A,而是使用组合而不是继承作为代码重用的机制来解决这个问题。也就是说,让B保留A的一个实例作为字段,并在适当的时候使用它。

如果你遇到一种罕见的情况,在不破坏Liskov的情况下,不可能对a进行子类化,那么你可以做一些事情来防止人们意外地对其进行子类,那就是明确地将a标记为最终的:

from typing import final
# If you want to support Python 3.7 or earlier, pip-install 'typing_extensions'
# and do 'from typing_extensions import final' instead
@final
class A: pass
class B(A): pass

这应该会使类型检查器在B的定义上报告"B不能子类化a"错误。如果您通过更改/删除B来修复该错误,那么对foo(B())的调用自然也会失败。

最新更新