为啥 Python 中没有 @override 装饰器来帮助提高代码的可读性? [关闭]

Posted

技术标签:

【中文标题】为啥 Python 中没有 @override 装饰器来帮助提高代码的可读性? [关闭]【英文标题】:Why no @override decorator in Python to help code readability? [closed]为什么 Python 中没有 @override 装饰器来帮助提高代码的可读性? [关闭] 【发布时间】:2016-04-03 22:10:31 【问题描述】:

我一直在使用ABCMeta 在 Python 中使用抽象类。当您编写一个抽象方法时,您使用装饰器@abstractmethod 对其进行标记。我发现奇怪的一件事(与其他语言不同)是,当子类覆盖超类方法时,没有提供像 @override 这样的装饰器。有谁知道这背后的逻辑可能是什么?

这使得阅读代码的人在快速确定哪些方法覆盖/实现抽象方法与仅存在于子类中的方法时会有些困惑。

【问题讨论】:

为什么需要提供装饰器?装饰器使您有机会用新对象替换函数,但在 Python 中不需要这样做,因为它会动态查找类上的名称(例如后期绑定),并以方法解析顺序 (MRO) 搜索类每一次。因此,子类中定义的方法自然地掩盖了父类中的方法。 而抽象方法的目标是确保它们被实现;您不能创建仍然存在抽象方法的类的实例。不是为了让它们与其他方法不同。 @MartijnPieters 在 Java 中应用了相同的行为 (MRO)。 @Override 注释只是为了帮助开发人员在编译时发现拼写错误(例如,如果方法名称拼写错误)。 @MartijnPieters 为真,但@abstractmethod 也强制用户实现该方法,而@Override 是可选的。 有人提出了一个类似于您正在寻找的实现:***.com/questions/1167617/… 【参考方案1】:

您将 Python 装饰器与 Java 注释混淆了。尽管语法相似,但它们是完全不同的东西。 Java 注释是对编译器的指令。但是 Python 装饰器是执行具体操作的可执行代码:它将函数包装在另一个函数中,该函数可以改变它的作用。 abstractmethod 的情况与任何其他装饰器一样。它做了一些事情,即告诉 ABC 有一个方法需要重写。

【讨论】:

请注意,如果您真的想要注释以提高自己的(可疑的)可读性,这样做既简单又便宜。 def override(func): return func。完毕。可用注解。有效地免费应用它(在导入时,您支付调用 noop 装饰器函数的微不足道的成本),玩得开心。 @ShadowRanger 我无法理解您的建议如何实现与 Java 提供的相同的 @Override 行为。 @alfasin:没有。它只是作为程序员的提示。它可以做更令人印象深刻的事情(尽管我怀疑它需要元类,因为装饰器会在方法附加到类之前单独应用)比如递归检查__bases__以验证继承链中方法的存在断言某些东西实际上被覆盖了,但如果主要目标是一种“语言内注释”,以您的代码库的标准化方式说“这覆盖了其他东西”,那么这样做。 @ShadowRanger @Override 不仅仅用于文档目的(为此,您可以毕竟添加代码注释......)。如果带注释的方法没有真的覆盖基类中的方法,它将导致编译失败。这是一个安全检查。添加“id 函数”作为装饰器不会提供这样的安全检查。 这与 Java 无关 - 您至少可以在 C++ 和 C# 中执行此操作。认为由于拼写错误或参数不匹配(这在 Python 中当然不会发生)而实际上并没有覆盖父类上的方法,这是任何有经验的程序员都犯过的令人讨厌且无声的错误不止一次。一个@overrides注解应该尽早导致失败,防止你默默地犯这样的错误。【参考方案2】:

尝试添加@override 的问题在于,在方法定义时,装饰器无法判断该方法是否实际上覆盖了另一个方法。它无权访问父类(或当前类,它甚至还不存在!)。

如果你想添加@override@override 装饰器实际上不能做任何覆盖检查。然后你有两个选择。要么没有覆盖检查,在这种情况下@override 并不比注释好,或者type 构造函数需要特别了解@override 并在类创建时检查它。像@override 这样的便利功能真的不需要像那样使类型系统实现的核心部分复杂化。此外,如果您不小心将@override 放在了非方法上,那么在您尝试调用修饰函数并得到一个奇怪的 TypeError 之前,该错误将不会被发现。

【讨论】:

这在 Python 3.6 中是不正确的。 @NeilG: 是的,现在有__set_name__,所以你可以实现一个@override 装饰器,它具有实际功能并且只有一些奇怪的交互(因为它必须返回一个自定义类型而不是一个普通函数)。 我会通过使用装饰器标记方法,然后在__init_subclass__ 中进行检查,这可以由基类提供。 @NeilG:如果您需要一个特定的超类,您可以在 3.6 之前的版本中使用元类完成这项工作(以与其他元类发生冲突为代价)。 @NeilG:嗯,abstractmethod 工作原理的一部分,因为它们也是baked some of the checks into object.__new__。我一直觉得设计需要一个特定的元类并且仍然将一些实现作为object.__new__ 的核心放在某个地方有点奇怪。看来如果他们要在object.__new__ 中放东​​西,他们还不如将ABCMeta 的功能直接折叠到type 中。

以上是关于为啥 Python 中没有 @override 装饰器来帮助提高代码的可读性? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 PyCharm 找不到正确版本的 pip 来安装 Python 模块?

为啥 Eclipse 在接口方法上抱怨 @Override?

你啥时候使用 Java 的 @Override 注解,为啥?

为啥在 C++ 中覆盖是可选的?

为啥装 node.js 要先装 python.python 起到了啥作用

为啥安装skimage后里面没有.util.montage模块