2012-09-17 31 views
6

我有以下代码:做操作符重载时,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源代码中显示这是如何工作的吗?

+0

附注:您知道'__cmp__'在几年前不赞成使用吗?您应该实施丰富比较功能。 – Bakuriu

+0

是的,当我试图找出是否应该在__eq__的实现中引发异常或返回NotImplemented时,就出现了这种情况。我想看看内建的Python类做了什么,并发现这个看起来不一致的例子。 – Chris

回答

5

的文档是不是在这一点上完全明确,但看到here

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

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

-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的源,你可以在功能wrap_cmpfunc找到原因导致typeobject.c这实际上检查了两件事情:给定比较函数是funcotherself的子类型。

if (Py_TYPE(other)->tp_compare != func && 
    !PyType_IsSubtype(Py_TYPE(other), Py_TYPE(self))) { 
// .... 
} 
+3

我不认为这解决了这个问题。我认为OP认识到他可以强制其他类型来进行比较工作。问题是*为什么他必须?*为什么'__cmp__'没有看到类型不一样并立即返回'False'? – mgilson

+4

问题是为什么会有两个不同的结果,而不是如何使'str'和'int'比较。 –

+0

已更新的答案。 –

3

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

  • 蟒蛇电话a.__cmp__(b)
    • a将检查b是一个合适的类型
    • 如果b是一个合适的类型,返回-10,或者+1
    • 如果b是不,返回NotImplented
  • 如果-10,或+1返回,蟒蛇完成;否则
  • 如果NotImplented返回,试图
  • b.__cmp__(a)
    • b将检查a是一个合适的类型
    • 如果a是一个合适的类型,返回-10,或+1
    • 如果a不是,返回NotImplemented
  • if -10+1返回,python完成;否则
  • 如果NotImplented再次返回,答案是False

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

+0

很好,但不能解释错误信息。 –