2012-08-07 46 views
5

完成以下代码的最自然的方法是什么?如何在实现比较运算符时处理混合类型?

import functools 

@functools.total_ordering 
class X: 
    def __init__(self, a): 
     self._a = a 

    def __eq__(self, other): 
     if not isinstance(other, X): 
      return False 
     return self._a == other._a 

    def __lt__(self, other): 
     if not isinstance(other, X): 
      return ...     // what should go here? 
     return self._a < other._a 

if __name__ == '__main__': 
    s = [2, 'foo', X(2)] 
    s.sort() 
    print s 

回答

2

你可以选择任何感觉自然的东西; False表示你的实例总是按照其他类型排序,True,它们将在之前被排序。

或者,您也可以返回NotImplemented(见the __lt__ and other comparison methods documentation)信号不支持比较:

def __lt__(self, other): 
    if not isinstance(other, X): 
     return NotImplemented 
    return self._a < other._a 

引用文档:

丰富的比较方法,如果它返回的单NotImplemented没有为给定的一对参数实现操作。按照惯例,返回FalseTrue以成功比较。但是,这些方法可以返回任何值,因此如果在布尔上下文中使用比较运算符(例如,在if语句的条件下),Python将调用bool()来确定结果是true还是false。

+1

只是返回False或True不是一个好主意。考虑这种情况,当你有另一个类似的类Y并且做X('foo') X('foo')。结果可能不一致。 – user763305 2012-08-07 12:24:35

+1

但是返回NotImplemented不起作用。然后,Python将使用自己的默认排序,这有点武断,但一致。 – user763305 2012-08-07 12:25:37

4

我个人的做法:

例外。

不同类型之间没有自然顺序。

官方之一:(选择这一项,应该有)

虽然我不同意这种说法完全手册明确指出它是如何要做到:

http://docs.python.org/library/stdtypes.html#comparisons

不同类型的对象,除了不同的数字类型和 不同的字符串类型,永远不会比较相等;这样的对象被一致但是任意地排列为 (以便排序异构阵列 产生一致的结果)。此外,某些类型(例如, 文件对象)仅支持简单的比较概念,其中任何类型的两个对象都不相等。同样,这些对象被任意但一致地订购 。当任何操作数是一个复数时,<,< =,>和> =运算符将引发TypeError异常 。

所以基本上......我会提出一个例外,但是排序的最pythonic方式是遵守手册。

应该有一个 - 最好只有一个 - 明显的方法来做到这一点。

+0

但是Python确实执行了这样的命令。我可以对列表进行排序[2.3,'foo',int]。 – user763305 2012-08-07 12:07:15

+0

'1''一个字符串'是假的,'1''一个字符串'是真的。 – 2012-08-07 12:08:00

+0

具体而言,'TypeError(“无法与{}格式(type(self),type(other)))进行比较。 – ecatmur 2012-08-07 12:09:09