是否可以仅键入提示 class 对象但排除子 class 对象?
Is it possible to type hint exclusively a class object but exclude subclass objects?
我想专门为特定 class 键入提示参数,但排除任何子 classes。
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 substitution principle——假设在设计用于处理父类的地方替换子类总是安全的。
它允许您在代码片段中除了传递 A 的实例之外还传递 B 的实例,这只是这一原则的一个例子。
因此,如果您的子类 B 被设计为 而不是 以遵循 Liskov 替换原则,那么它可能一开始就不是真正的 "kind of" 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 cannot subclass A" 错误。如果您通过 changing/deleting B
修复该错误,则调用 foo(B())
自然也应该无法进行类型检查。
我想专门为特定 class 键入提示参数,但排除任何子 classes。
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 substitution principle——假设在设计用于处理父类的地方替换子类总是安全的。
它允许您在代码片段中除了传递 A 的实例之外还传递 B 的实例,这只是这一原则的一个例子。
因此,如果您的子类 B 被设计为 而不是 以遵循 Liskov 替换原则,那么它可能一开始就不是真正的 "kind of" 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 cannot subclass A" 错误。如果您通过 changing/deleting B
修复该错误,则调用 foo(B())
自然也应该无法进行类型检查。