Python 是否可以只键入一个类对象而排除子类对象?

Python 是否可以只键入一个类对象而排除子类对象?,python,python-3.x,type-hinting,Python,Python 3.x,Type Hinting,我想专门为特定类键入一个参数,但不包括任何子类 A类: 通过 BA类: 通过 def fooobj:A: 通过 fooB我希望类型检查器在这里警告我,它需要A,而不是B 这可能吗?如果是,怎么做 如果你能告诉我这叫什么,我会给你加分。谷歌搜索没有帮助,但我恐怕我用了错误的术语来描述这一点不,这是不可能的 基本上,Python类型化生态系统假定您遵循-假定在设计用于处理父类的位置替换子类总是安全的 事实上,它允许您在代码段中除了传递A的实例外,还传递B的实例,这只是这一原则的一个例子 因此,如果你

我想专门为特定类键入一个参数,但不包括任何子类

A类: 通过 BA类: 通过 def fooobj:A: 通过 fooB我希望类型检查器在这里警告我,它需要A,而不是B 这可能吗?如果是,怎么做


如果你能告诉我这叫什么,我会给你加分。谷歌搜索没有帮助,但我恐怕我用了错误的术语来描述这一点

不,这是不可能的

基本上,Python类型化生态系统假定您遵循-假定在设计用于处理父类的位置替换子类总是安全的

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

因此,如果你的子类B不是为了遵循Liskov替换原理而设计的,那么它可能从来就不是一种真正的a,也不应该是它的子类

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

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

从键入import final开始 如果您想支持Python3.7或更早版本,请安装“typing_extensions” 并改为“从键入扩展导入最终” @决赛 甲级:及格 BA级:及格
这将使您的类型检查器报告a B不能在B的定义上对a错误进行子类化。如果您通过更改/删除B来修复该错误,对fooB的调用自然也将无法进行类型检查。

否,这是不可能的

基本上,Python类型化生态系统假定您遵循-假定在设计用于处理父类的位置替换子类总是安全的

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

因此,如果你的子类B不是为了遵循Liskov替换原理而设计的,那么它可能从来就不是一种真正的a,也不应该是它的子类

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

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

从键入import final开始 如果您想支持Python3.7或更早版本,请安装“typing_extensions” 并改为“从键入扩展导入最终” @决赛 甲级:及格 BA级:及格
这将使您的类型检查器报告a B不能在B的定义上对a错误进行子类化。如果您通过更改/删除B来修复该错误,对fooB的调用自然也将无法进行类型检查。

这似乎是糟糕的OO设计。任何接受一个类的东西都应该接受它的任何子类。我不知道有什么方法可以做到这一点。它没有包含在类型暗示中,可能是出于上述原因。也许可以将A和B作为一个公共基类的独立子类?使用mypy,它专门告诉需要提示的类型。您可以从命令行使用mypy,也有pycharm插件可供使用。偶尔有正当的理由这样做,例如,当一个函数是一个特定的优化代码路径,它假设没有重写任何方法,但是Python的类型提示系统不支持它。这看起来像是糟糕的OO设计。任何接受一个类的东西都应该接受它的任何子类。我不知道有什么方法可以做到这一点。它没有包含在类型暗示中,可能是出于上述原因。也许可以将A和B作为一个公共基类的独立子类?使用mypy,它专门告诉需要提示的类型。您可以从命令行使用mypy,也有pycharm插件可供使用。偶尔有正当的理由这样做,例如,一个函数是一个特定的优化代码路径,它假定没有重写任何方法,但Python的类型提示系统不支持它。