执行运算符重载时python是否强制类型?

时间:2012-09-17 18:12:45

标签: python

我有以下代码:

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运行时是否捕获int.__cmp__()抛出的TypeError,并将其解释为False值?有人能指出我在2.x cpython源代码中显示这是如何工作的吗?

3 个答案:

答案 0 :(得分:5)

关于这一点,文档并不完全明确,但请参阅here

  

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

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

答案 1 :(得分:3)

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

  • python调用a.__cmp__(b)
    • a检查b是否合适类型
    • 如果b是合适的类型,请返回-10+1
    • 如果b不是,请返回NotImplented
  • 如果-10+1返回,则python已完成;否则
  • 如果返回NotImplents,请尝试
  • b.__cmp__(a)
    • b检查a是否合适类型
    • 如果a是合适的类型,请返回-10+1
    • 如果a不是,请返回NotImplemented
  • 如果-10+1返回,则python已完成;否则
  • 如果再次返回NotImplented,答案为False

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

答案 2 :(得分:-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的{​​{1}}中找到这个结果的原因,它实际检查了两件事:给定比较函数是wrap_cmpfunc和{{ 1}}是func的子类型。

other