6

我有以下代码:

a = str('5')
b = int(5)
a == b
# False

但是,如果我创建 , 的子类int并重新实现__cmp__

class A(int):
    def __cmp__(self, other):
        return super(A, self).__cmp__(other)
a = str('5')
b = A(5)
a == b
# TypeError: A.__cmp__(x,y) requires y to be a 'A', not a 'str'

为什么这两个不同?python 运行时是否捕获了由 抛出的 TypeErrorint.__cmp__()并将其解释为一个False值?有人可以指出我在 2.x cpython 源代码中显示它是如何工作的位吗?

4

3 回答 3

5

该文档在这一点上并不完全明确,但请参见此处

如果两者都是数字,则将它们转换为通用类型。否则,不同类型的对象总是比较不相等,并且顺序一致但任意。__cmp__您可以通过定义方法或丰富的比较方法来控制非内置类型对象的比较行为__gt__,如特殊方法名称部分所述。

这(特别是“不同类型的对象”和“非内置类型的对象”之间的隐含对比)表明,对于内置类型,实际调用比较方法的正常过程被跳过:如果你尝试比较两种不同的(和非数字的)内置类型,它只是短路到自动 False。

于 2012-09-17T18:40:20.803 回答
3

比较决策树a == b看起来像:

  • 蟒蛇调用a.__cmp__(b)
    • a检查是否b是适当的类型
    • 如果b是适当的类型,则返回-1, 0, 或+1
    • 如果b不是,则返回NotImplented
  • 如果-1,,0+1返回,python 完成;除此以外
  • 如果 NotImplented 返回,请尝试
  • b.__cmp__(a)
    • b检查是否a是适当的类型
    • 如果a是适当的类型,则返回-1, 0, 或+1
    • 如果a不是,则返回NotImplemented
  • 如果-1,,0+1返回,python 完成;除此以外
  • 如果 NotImplented 再次返回,答案是False

不是一个确切的答案,但希望它有所帮助。

于 2012-09-17T18:49:14.123 回答
-2

如果我理解你的问题是正确的,你需要这样的东西:

>>> class A(int):
...     def __cmp__(self, other):
...         return super(A, self).__cmp__(A(other)) # <--- A(other) instead of other
... 
>>> a = str('5')
>>> b = A(5)
>>> a == b
True

更新

关于 2.x cpython 源代码,您可以在实际检查两件事typeobject.c的函数中找到导致此结果的原因:给定的比较函数是 a并且是.wrap_cmpfuncfuncotherself

if (Py_TYPE(other)->tp_compare != func &&
    !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) {
// ....
}
于 2012-09-17T18:17:57.407 回答