代码之家  ›  专栏  ›  技术社区  ›  Singletoned

为什么在python中'x==y'调用'y.'\uuueq(x)`?

  •  37
  • Singletoned  · 技术社区  · 15 年前

    python文档清楚地指出 x==y 电话 x.__eq__(y) . 然而,在许多情况下,情况似乎恰恰相反。它记录了什么时候或者为什么会发生这种情况,以及我如何确定我的对象是否 __cmp__ __eq__ 方法将被调用。

    编辑:为了澄清,我知道 爱斯克 在preferrecne中调用为 α-CMPa 但是我不清楚为什么 y.__eq__(x) 优先调用 x.y-ε(y) 当后者是将要发生的文档状态时。

    >>> class TestCmp(object):
    ...     def __cmp__(self, other):
    ...         print "__cmp__ got called"
    ...         return 0
    ... 
    >>> class TestEq(object):
    ...     def __eq__(self, other):
    ...         print "__eq__ got called"
    ...         return True
    ... 
    >>> tc = TestCmp()
    >>> te = TestEq()
    >>> 
    >>> 1 == tc
    __cmp__ got called
    True
    >>> tc == 1
    __cmp__ got called
    True
    >>> 
    >>> 1 == te
    __eq__ got called
    True
    >>> te == 1
    __eq__ got called
    True
    >>> 
    >>> class TestStrCmp(str):
    ...     def __new__(cls, value):
    ...         return str.__new__(cls, value)
    ...     
    ...     def __cmp__(self, other):
    ...         print "__cmp__ got called"
    ...         return 0
    ... 
    >>> class TestStrEq(str):
    ...     def __new__(cls, value):
    ...         return str.__new__(cls, value)
    ...     
    ...     def __eq__(self, other):
    ...         print "__eq__ got called"
    ...         return True
    ... 
    >>> tsc = TestStrCmp("a")
    >>> tse = TestStrEq("a")
    >>> 
    >>> "b" == tsc
    False
    >>> tsc == "b"
    False
    >>> 
    >>> "b" == tse
    __eq__ got called
    True
    >>> tse == "b"
    __eq__ got called
    True
    

    编辑:从Mark Dickinson的回答和评论来看:

    1. 丰富的比较覆盖 α-CMPa
    2. 爱斯克 是自己的吗? __rop__ 对它 __op__ (类似于 __lt__ , __ge__ 等)
    3. 如果左对象是内置类或新样式类,而右对象是其子类,则右对象的 爱罗普斯 在左对象的 α-π

    这就解释了 TestStrCmp 例子。 测试程序 是的子类 str 但不实现自己的 爱斯克 所以 爱斯克 属于 STR 在这两种情况下优先(即 tsc == "b" 电话 b.__eq__(tsc) 作为一个 爱罗普斯 因为规则1)。

    TestStrEq 例子, tse.__eq__ 在两个实例中都调用,因为 斯特斯特雷克 是的子类 STR 所以它被称为优先权。

    TestEq 例子, 泰斯特 器具 爱斯克 int 不是这样 爱斯克 两次都被调用(规则1)。

    但我还是不理解第一个例子 TestCmp . tc 不是上的子类 int 因此, 1.__cmp__(tc) 应该打电话,但不是。

    4 回复  |  直到 15 年前
        1
  •  30
  •   Daniel Pryden    15 年前

    您缺少一个常见行为的键异常:当右侧操作数是左侧操作数类的子类的实例时,首先调用右侧操作数的特殊方法。

    请参阅文档:

    http://docs.python.org/reference/datamodel.html#coercion-rules

    尤其是以下两段:

    对于对象 x y ,首先 x.__op__(y) 试过了。如果这不是 执行或返回 NotImplemented , y.__rop__(x) 是 尝试。如果这也没有实现 或返回 无刺激的 A 引发了类型错误异常。但是你看 以下例外情况:

    上一项的例外情况:如果 左操作数是 内置式或新样式的类, 右操作数是一个实例 属于该类型的一个子类或 类并重写基_ __rop__() 方法,正确的 操作数 α-ROPp*() 方法尝试 左操作数“s”之前 __op__() 方法。

        2
  •  6
  •   Dancrumb    15 年前

    实际上,在 docs 它指出:

    [ __cmp__ 如果没有定义富比较(见上文),则由比较操作调用。

    __eq__ 是一种丰富的比较方法, TestCmp ,未定义,因此调用 α-CMPa

        3
  •  1
  •   Mikhail Churbanov    15 年前

    正如我所知, __eq__() 是一种所谓的“富比较”方法,用于比较运算符而不是 __cmp__() 下面。 α-cMP*() 如果未定义“富比较”,则调用。

    所以在a==b:
    如果 _公式 在中定义,它将被调用
    否则 α-cMP*() 将被称为

    α-ε() 在“str”中定义,因此 α-cMP*() 未调用函数。

    同样的规则也适用于 __ne__(), __gt__(), __ge__(), __lt__() __le__() “丰富的比较”方法。

        4
  •  1
  •   dubiousjim    15 年前

    这是否没有记录在 Language Reference ?从那里看,它看起来像 __cmp__ 被忽略时 __eq__ , __lt__ 等已定义。我理解这一点,把案件包括在 爱斯克 在父类上定义。 str.__eq__ 已经定义了,所以 α-CMPa 它的子类将被忽略。 object.__eq__ ETC没有这样定义 α-CMPa 它的子类将得到尊重。

    针对澄清的问题:

    我知道。 爱斯克 被调用 优先于 α-CMPa 但我不是 清楚为什么 y.__eq__(x) 被调用 首选 x.__eq__(y) 当 后者是文档的状态 发生。

    博士说 x.y-ε(y) 将首先调用,但它有返回的选项 NotImplemented 在这种情况下 Y.E.E.Qq*(x) 被称为。我不知道你为什么相信这里发生了一些不同的事情。

    你对哪件事特别困惑?我理解你只是对 "b" == tsc tsc == "b" 箱子,对吗?在任何一种情况下, str.__eq__(onething, otherthing) 正在被呼叫。因为你不重写 爱斯克 方法在testsrcmp中,最终只依赖于基字符串方法,它表示对象不相等。

    不知道 斯特朗 ,我不知道 ("b").__eq__(tsc) 将返回 无刺激的 给TSC一个机会来处理平等测试。但即使这样,按照定义testsrcmp的方式,仍然会得到一个错误的结果。

    所以不清楚你在这里看到了什么,这是意想不到的。

    也许发生的是巨蟒更喜欢 爱斯克 α-CMPa 如果定义在 任何一个 被比较的对象,而您期望 α-CMPa 在最左边的对象上优先于 爱斯克 在右手边的物体上。是这样吗?