python 与 __le__、__ge__ 的错误?

2023-11-25

是我还是Python对以下代码感到困惑?我希望__le__被称为a <= ab, not __ge__:

#!/usr/bin/env python2

class B(object):
    def __ge__(self, other):
        print("__ge__ unexpectedly called")

class A(object):
    def __le__(self, other):
        print("__le__ called")

class AB(A, B):
    pass

a = A()
ab = AB()

a <= ab # --> __ge__ unexpectedly called
ab <= a # --> __le__ called

我在 python 2.7、3.2 和 pypy 1.9 中得到了相同的行为。

我该怎么做才能得到__le__调用而不是__ge__ ??


简短的回答是他们希望允许AB覆盖行为A。 Python无法调用AB.__lt__(a, ab), 因为a可能不是有效的self for an AB方法,因此它调用AB.__gt__(ab, a),这是有效的。

长答案有点复杂。

根据文档丰富的比较运算符:

这些方法没有交换参数版本(当左侧参数不支持该操作但右侧参数支持该操作时使用);相当,__lt__() and __gt__()都是彼此的倒影,__le__() and __ge__()是彼此的反映,并且__eq__() and __ne__()是他们自己的反映。

换句话说,x <= y将会通知y.__ge__(x)在完全相同的情况下x+y会打电话y.__radd__(x)。比较:

>>> class X(object):
...     def __add__(self, other):
...         print('X.add')
>>> class Y(object):
...     def __radd__(self, other):
...         print('Y.radd')
>>> class XY(X, Y):
...     pass
>>> x, xy = X(), XY()
>>> x + xy
Y.radd

根据文档反射算子:

调用这些方法来实现带有反射(交换)操作数的二进制算术运算。仅当左操作数不支持相应操作且操作数类型不同时才会调用这些函数......

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

所以,因为XY是一个子类X, XY.__radd__优先于X.__add__。并且,同样,因为AB是一个子类A, AB.__ge__优先于A.__le__.

这可能应该更好地记录下来。要弄清楚这一点,您必须忽略括号“当左参数不支持该操作但右参数支持该操作时使用”,猜测您需要查找正常的交换运算符(没有链接,甚至提到,此处),然后忽略“仅当左操作数不支持相应操作时才调用这些函数”的措辞,并参见“注释”,这与上面的内容相矛盾......还要注意文档明确指出,“比较运算符之间没有隐含的关系”,只有在描述交换的情况之前的一段,这暗示了正是这样的关系......

最后,这个案例看起来很奇怪,因为AB,而不是覆盖__ge__本身,只是继承自B,它一无所知A并且与之无关。想必B不打算让其子类覆盖A的行为。但如果B旨在用作 mixinA- 派生类,也许吧would正是打算这样的覆盖。无论如何,如果不考虑 MRO 中每种方法的来源,该规则可能已经足够复杂了。无论出于何种原因,__ge__来自是无关紧要的;如果它存在于子类中,则会调用它。

对于您添加的最后一个问题,“我该怎么做才能获得__le__调用而不是__ge__??“……好吧,你真的不能,比你能得到的更多X.__add__调用而不是XY.__radd__。当然,您始终可以实施AB.__ge__ (or XY.__radd__) 调用A.__le__ (or X.__add__),但实施起来可能更容易AB.__ge__以这样的方式,它可以与A首先作为它的另一个论点。或者,您可以删除继承并找到其他方法来对您以这种方式建模的任何内容进行建模。或者你可以明确地调用a.__le__(ab)代替a<=ab。但除此之外,如果您以利用“无隐含关系”的方式设计类来做一些奇怪的事情,那么您就会被文档误导,并且必须以某种方式重新设计它们。

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

python 与 __le__、__ge__ 的错误? 的相关文章

  • python - 如何删除每行中的重复列表(pandas)?

    我的每一行中都包含一个列表 我想通过保留分数中的最高值来删除重复元素 这是我的数据框 df1 中的数据 pair score 0 A A 1 0000 1 A F 0 9990 2 A G 0 9985 3 A G 0 9975 4 A H
  • 将 ical 附件的邮件消息的内容类型设置为“text/calendar; method=REQUEST”

    我正在尝试使用 App Engine 邮件 API 从 App Engine 发送 iCalendar 格式的 ics 文件 这在 GMail 中非常有效 但是 Outlook 无法识别该文件 我认为问题在于内容类型设置为 文本 日历 而不
  • 如何并排绘制具有相同 X 坐标的条形图(“闪避”)

    import matplotlib pyplot as plt gridnumber range 1 4 b1 plt bar gridnumber 0 2 0 3 0 1 width 0 4 label Bar 1 align cente
  • 在二维数组中进行所有可能的组合

    我正在尝试制作具有所有可能组合的 4x4 16 像素黑白图像数组 我制作了以下数组作为模板 template 0 0 0 0 start with all white pixels 0 0 0 0 0 0 0 0 0 0 0 0 然后我想迭
  • 学习Python中的解析器

    我记得我读过有关解析器的内容 您只需提供一些示例行 它就知道如何解析某些文本 它只是确定两条线之间的差异 以了解可变部分是什么 我以为它是用 python 写的 但我不确定 有谁知道那是什么图书馆吗 可能你的意思是模板制作器 http co
  • 删除 tkinter 文本默认绑定

    我正在制作一个简单的 tkinter 文本编辑器 但我想要所有默认绑定文本小部件如果可能的话删除 例如当我按Ctrl i它默认插入一个制表符 我制作了一个事件绑定来打印文本框中有多少行 我将事件绑定设置为Ctrl i以及 当我运行它时 它会
  • 如何在plotly(python)中的刻度标签和图形之间添加空格?

    如果我使用绘图创建水平条形图 则每个条形的标签都与图表相对应 我想在标签和图表之间添加一些空间 填充 边距 我怎样才能做到这一点 Example import plotly offline as py import plotly graph
  • 无法使用Python请求会话模块登录网站

    我刚刚开始进行网络抓取 对于我的第一个项目 我尝试使用 requests Session 登录 artofproblemsolving com 并访问另一个用户的帐户 这是我的代码 import requests LOGIN URL htt
  • 将列表值转换为 pandas 中的行

    我有数据帧 其中一列具有相同长度的 numpy ndarray 值 df list 0 Out 92 array 0 0 0 0 29273096 0 30691767 0 27531403 我想将这些列表值转换为数据框并从 df iloc
  • lmfit模型拟合然后预测

    我正在领养lmfit进行曲线拟合并使用拟合模型进行预测 然而下面的代码并没有达到我想要的效果 能否请你帮忙 谢谢 import numpy as np from lmfit import Model def linearModel x a0
  • Python 中“is”运算符的语义是什么?

    如何is运算符确定两个对象是否相同 它是如何工作的 我找不到它的记录 来自文档 http docs python org reference datamodel html 每个对象都有一个身份 一个类型 和一个值 对象的身份 一旦发生就永远
  • 尝试校准keras模型

    我正在尝试通过 Sklearn 实现来校准我的 CNN 模型CalibratedClassifierCV 尝试将其包装为KerasClassifier并覆盖预测功能但没有成功 有人可以说我做错了什么吗 这是模型代码 def create m
  • Python FTP下载550错误

    我编写了一个 ftp 爬虫来下载特定文件 它会一直工作 直到找到要下载的特定文件 然后抛出此错误 ftplib error perm 550 该文件存在于我的下载文件夹中 但文件大小为 0 kb 我需要转换某些内容才能下载吗 我可以访问 f
  • matplotlib vlines 图中未应用 y 轴的最小值

    我正在 matplotlib 中绘制 vlines 图 数据集中的所有 y 值如下 gt 0 我希望 y 轴最底部的刻度能够读取0 但相反 我得到 500 这是代码 usr bin env python import numpy as np
  • Pygame:有人可以帮我实现双跳吗?

    我知道已经有其他关于此问题的帖子了 但我的运动系统与我发现的有点不同 所以随后我问这个问题 我的运动系统基于一个名为的命名元组Move up left right down 然后就是这个 def update self move block
  • 使用具有可变数量索引的 numpy mggrid

    如何将 numpy mgrid 与可变数量的索引一起使用 我在 github 上找不到任何人将其与硬编码值以外的任何内容一起使用的示例 import numpy as np np mgrid 1 10 1 10 this works fin
  • Python GTK3 Treeview 向上或向下移动选择

    如何在树视图中向上或向下移动所选内容 我的想法是 我可以使用向上和向下按钮将选择向上移动一行或向下移动一行 我的 Treeview 使用 ListStore 不确定这是否重要 首先 我将使用我熟悉的 C 代码 如果您在将其翻译为 Pytho
  • 在字符串内打印单引号

    我想输出 XYZ s ABC 我在Python IDLE中尝试了以下3条语句 第一条和第二条语句输出 a before 带打印功能的第三条语句不输出 before 作为 Python 新手 我想了解为什么 之前输出 在第 1 条和第 2 条
  • 如何在类型提示中定义元组或列表的大小

    有没有办法在参数的类型提示中定义元组或列表的大小 目前我正在使用这样的东西 from typing import List Optional Tuple def function name self list1 List Class1 if
  • 如何仅读取 CSV 文件每行的第一列 [重复]

    这个问题在这里已经有答案了 如何在Python中读取CSV文件每行的第一列 我的数据是这样的 1 abc 2 bcd 3 cde 我只需要循环第一列的值 另外 当我在 calc 中打开 csv 文件时 每行中的数据都在同一个单元格中 这正常

随机推荐