是否可以仅以提示方式键入类对象,但排除子类对象?

问题描述 投票:0回答:1

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

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 python-3.x pycharm type-hinting
1个回答
1
投票

不,这是不可能的。

从根本上说,Python类型化生态系统假定您遵循Liskov substitution principle -假定在设计用于处理父级的位置替换子类始终是安全的。

它允许您在代码段中除了A实例之外还传递B实例,这只是这种原理在起作用的一个例子。

因此,如果您的子类B被设计为[[not来遵循Liskov替换原理,那么可能从一开始它就不是真正的A类,也不应该对其进行子类化。

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

[如果遇到极少数情况,在不破坏Liskov的情况下合法地不可能继承A的情况,那么可以防止他人意外地继承它,您可以做的就是将A明确标记为final

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())的调用自然也应该无法键入-检查。
© www.soinside.com 2019 - 2024. All rights reserved.