python的a==b调用b.__eq__(a),对于没有覆盖的子类[重复]

2024-06-28

在 python 2.7.6 中,假设我有一个类定义__eq__和一个子类 其中:

>>> class A(object):
...     def __eq__(self,other):
...         print self.__class__,other.__class__
...         return True
... 
>>> class B(A):
...     pass
... 

现在我创建每个类的一个对象,并想要比较它们:

>>> a = A()
>>> b = B()
>>> a==b

我得到的结果:

<class '__main__.B'> <class '__main__.A'>

这表明解释器正在调用b.__eq__(a), 代替a.__eq__(b)作为 预期的。

The 文档 https://docs.python.org/release/2.7.6/reference/datamodel.html#coercion-rules%20documentation状态(强调):

  • 对于物体x and y, first x.__op__(y)已尝试。如果未实现或返回NotImplemented, y.__rop__(x)已尝试。如果这也没有实现或返回NotImplemented, a TypeError引发异常。但看到以下异常:

  • 上一项的例外情况:如果左操作数是内置类型或新式类的实例,而右操作数是该类型或类的真子类的实例并覆盖基地的__rop__() method, 右操作数的__rop__()在左操作数之前尝试方法__op__() method.

    这样做是为了让子类可以完全重写二元运算符。否则,左操作数的__op__()方法将始终接受正确的操作数:当需要给定类的实例时,该类的子类的实例始终是可接受的。

自从有了子类B不覆盖__eq__运营商,不应该a.__eq__(b)被称为而不是b.__eq__(a)?这是预期的行为还是错误?这与我阅读的文档相反:我是否误读了文档或遗漏了其他内容?

一些相关问题:

  • 这个答案 https://stackoverflow.com/a/2282795/407588引用我上面引用的文档。在这种情况下,最后一个问题涉及内置类型 (1) 的对象和实例之间的比较 一个新风格的班级。在这里,我专门比较父类的实例 与一个子类的实例does not覆盖rop()其方法 父级(在本例中,__eq__既是op() and rop()).

    在这种情况下,python 实际上确实调用了b.__eq__(a)代替a.__eq__(b)首先,尽管上课B没有显式覆盖A.


看起来子类被认为“覆盖”超类行为,即使它所做的只是继承超类行为。这在__eq__案例因为__eq__是它自己的反射,但是如果使用不同的运算符,你可以更清楚地看到它,例如__lt__ and __gt__,这是彼此的反射:

class A(object):
    def __gt__(self,other):
        print "GT", self.__class__, other.__class__

    def __lt__(self,other):
        print "LT", self.__class__, other.__class__

class B(A):
    pass

Then:

>>> A() > B()
LT <class '__main__.B'> <class '__main__.A'>

注意A.__gt__没有被叫到;反而,B.__lt__被称为。

The Python 3 文档 https://docs.python.org/3/reference/datamodel.html#object.__ror__是说明性的,因为它用不同的词语陈述了规则,这些词语在技术上更准确(强调是添加的):

如果右操作数的类型是左操作数类型的子类并且该子类provides该操作的反射方法,该方法将在左操作数的非反射方法之前被调用。这种行为允许子类覆盖其祖先的操作。

子类确实“提供”了反射方法,它只是通过继承提供它。如果您实际上删除了子类中反射的方法行为(通过返回 NotImplemented),则超类方法将被正确调用(在子类方法之后):

class A(object):
    def __gt__(self,other):
        print "GT", self.__class__, other.__class__

    def __lt__(self,other):
        print "LT", self.__class__, other.__class__

class B(A):
    def __lt__(self, other):
        print "LT", self.__class__, other.__class__
        return NotImplemented

>>> A() > B()
LT <class '__main__.B'> <class '__main__.A'>
GT <class '__main__.A'> <class '__main__.B'>

所以基本上这似乎是一个文档错误。应该说子类反射的方法是always首先尝试(对于比较运算符),无论子类是否显式覆盖超类实现。 (不过,正如 Mark Dickinson 在评论中指出的那样,它仅适用于比较运算符,不适用于数学运算符对,例如__add__/__radd__.)

在实践中,这不太重要,因为您唯一注意到它是当子类doesn't覆盖超类。但在这种情况下,子类的行为根据定义与超类的行为相同,因此调用哪一个并不重要(除非您正在做一些危险的事情,例如从比较方法中改变对象,在这种情况下无论如何你应该保持警惕)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python的a==b调用b.__eq__(a),对于没有覆盖的子类[重复] 的相关文章

随机推荐

  • 为什么 Xcode 会在钥匙串中自动安装(重复且过期的)证书? [复制]

    这个问题在这里已经有答案了 可能的重复 xCode 4 重新安装我删除的钥匙串证书 https stackoverflow com questions 5264481 xcode 4 reinstalls keychain certs th
  • MATLAB:检测并删除 2 列矩阵中的镜像对

    我有一个矩阵 1 2 3 6 7 1 2 1 并想删除镜像对 即输出将是 1 2 3 6 7 1 or 3 6 7 1 2 1 有没有一种简单的方法可以做到这一点 我可以想象一个复杂的 for 循环 例如 或不会删除原始对的版本 仅删除重复
  • swift - 仅在落地时跳跃

    我希望限制我的角色 猫 使其仅在地面 虚拟 SKNode 或树上 treeP SKNode 时跳跃 目前我没有任何限制touchesBegan因此 如果用户快速连续点击 猫就能够在空中飞翔 虽然这在其他游戏中可能很有用 但在这里不受欢迎 如
  • 如何处理 Volley StringRequest 中的空值

    我有一个返回 2 组不同值的响应 在每种情况下 都会有一个值always为空 另一个将为空always包含一个值 问题是 Volley 不允许我分配 null JSON 值或在 if 语句中检查 JSON 值 它只是指 catch 块 我正
  • Chrome getUserMedia 未在本地请求权限

    我正在尝试在 Chrome 中使用 navigator getUserMedia 但是 它在本地提供时不会请求权限 file whatever index html 但在 JSFiddle 上会请求权限 http jsfiddle net
  • flex 4 tabbar - 禁用选项卡

    有没有一种常见的方法可以在 Flex 4 中禁用 Spark TabBar 组件的选项卡 使用 mx tabnavigator 组件 您可以禁用与选项卡相对应的内容 然后选项卡也会被禁用 但是使用 Spark 选项卡栏组件执行此操作只会禁用
  • 如何正确处理聊天消息应用程序的“已读”-“未读”状态?

    我目前正在开发一个反应本机应用程序 该应用程序使用 socket io 提供聊天室功能 我目前愿意处理消息的未读 已读状态 但我不知道该逻辑应位于何处 在客户端代码中还是在服务器端 这是我的代码组件的基本实现
  • Flutter中如何获取当前路由路径?

    在实施的同时持久底部栏 https stackoverflow com questions 45511549 permanent view with navigation bar in flutter 以前的路线需要恢复 https git
  • 将最新的 R 安装路径从注册表添加到 PATH windows 7/8/10

    嗨 我是 Windows 批处理新手 我想向打电话的同事分发一个 runMe bat 文件Rscript myRfile R处理一些数据文件 但众所周知 我的同事在不同地方安装了 R 我不能指望他们知道如何将 Rscript 添加到 PAT
  • appcompat-v7:27.1.1 与 play-services:11.0.1 冲突

    我正在开发一个新应用程序 目前我正在尝试添加依赖项 implementation com google android gms play services 11 0 1 当我这样做时 我在实现 com android support app
  • FlowLayoutPanels 中的 C# 拖放标签

    我有一个小问题 我想要制作一个程序 可以在多个 FlowLayoutPanel 之间拖动生成的标签 但最近几天我尝试让拖放工作 我尝试了很多教程 示例等 但总是有些不同 而且我无法仅提取基本代码 它类似于这个程序 https social
  • 使用 JavaScript 清理 SQL 数据

    我有一堆具有各种输入元素的表单 我想在服务器端清理这些 yes 我使用服务器端 JavaScript 将这些输入用作参数 并防止特殊字符格式错误 在你走之前 比如 这不属于 JavaScript 的领域 等等 我正在使用一个价值数百万美元的
  • 使用 localinstall 更新 yum 包

    如果使用安装包yum 本地安装像这样 yum y localinstall nogpgcheck some package 1 0 0 rpm 现在 如果我尝试运行 yum y localinstall nogpgcheck some pa
  • 在 python numpy 中构建一个 nxn 矩阵,对于任何 n

    是否可以使用 python 的 numpy 版本 3 3 编写构建 nxn 矩阵的代码 而不指定 n 我需要将条目索引为 A i j 或类似的东西 但我什至不知道如何定义 A i j 以便它们实际上是对象 我认为这样的事情可能会起作用 n
  • 使用 MVC3 C# 进行分页的最简单方法?

    在 MVC3 C 中有一个网站项目 我从数据库中检索信息并在我的视图中以表格形式呈现 我想使用分页来每页最多显示五行 一直在互联网上寻找教程 但它们似乎都非常先进 可以实现这一目标 使用 MVC3 进行分页的最简单方法是什么 看图片左下角就
  • Django + Nginx 配置(获取“Welcome to nginx!”)

    我在 Ubuntu 上有 Django Nginx Gunicorn 使用 Letscrypt 生成的证书 In etc nginx sites available myproject I have server server name m
  • VB中CLS文件和DLL文件的用途是什么?

    有谁对 VB 项目中的 CLS DLL 和 VBP 文件的不同含义有很好的解释吗 CLS 文件是包含一个类的源代码的类文件 VBP文件是一个项目文件 您在 VB6 IDE 中打开 VBP 来浏览或编辑该项目的代码 项目也可以包含在组中 VB
  • 如何使用带有外键的时间尺度超表并保持一对多关系?

    我正在尝试创建一个考虑到最小冗余的数据库 我们想使用 timescaledb 超级表 我运行 postgreSQL v 12 和 timescaledb v 1 7 4 创建表的 postgreSQL 代码如下 您可以在此处查看 dbdia
  • 使用java连接到SFTP

    我需要有关连接 SFTP 服务器的帮助吗 有人有工作代码吗 我发现了这样的东西 package test JSch import com jcraft jsch public class TestJSch public static voi
  • python的a==b调用b.__eq__(a),对于没有覆盖的子类[重复]

    这个问题在这里已经有答案了 在 python 2 7 6 中 假设我有一个类定义 eq 和一个子类 其中 gt gt gt class A object def eq self other print self class other cl