2012-04-07 45 views
5

the manual是说:最小方法在Python鸭打字订购3.1

in general, __lt__() and __eq__() are sufficient, if you want the conventional meanings of the comparison operators

但我看到的错误:

>  assert 2 < three 
E  TypeError: unorderable types: int() < IntVar() 

当我运行这个测试:

from unittest import TestCase 

class IntVar(object): 

    def __init__(self, value=None): 
     if value is not None: value = int(value) 
     self.value = value 

    def __int__(self): 
     return self.value 

    def __lt__(self, other): 
     return self.value < other 

    def __eq__(self, other): 
     return self.value == other 

    def __hash__(self): 
     return hash(self.value) 

class DynamicTest(TestCase): 

    def test_lt(self): 
     three = IntVar(3) 
     assert three < 4 
     assert 2 < three 
     assert 3 == three 

我很惊讶,当IntVar()在右边,__int__()没有被调用。我究竟做错了什么?

添加__gt__()修复了这个,而是指我不明白的最低要求是订购...

感谢, 安德鲁

+0

如果你看[丰富比较方法文档](http://docs.python.org/release/3.1.3/reference/datamodel.html#object.__lt__),它特别提到了这种行为 - 'There没有这些方法的交换参数版本(当左边的参数不支持这个操作,但是正确的参数的时候使用);相反,__lt __()和__gt __()是彼此的反射,__le __()和__ge __()是彼此的反射,__eq __()和__ne __()是他们自己的反射。 丰富的比较方法的参数从未被强制。# – agf 2012-04-07 13:45:17

+0

@agf:答案应该在答案中,而不是在评论中。 – 2012-04-07 15:56:36

+0

@EthanFurman虽然Sven的回答确实如此,但文档并没有引导你,而IMO则认为这不仅仅是一个评论,而是一个回答。 – agf 2012-04-07 16:46:02

回答

4

Python 3.x都有永远不会做任何运营商的强制类型转换,因此__int__()未在此上下文中使用。比较

a < b 

都会先打电话type(a).__lt__(a, b),如果这个返回NotImplemented,它会调用type(b).__gt__(b, a)

来自文档的引用是关于对单个类型进行比较,上面的解释说明了为什么这对单个类型来说足够了。

为了使您的类型与int正确交互,您应该实现所有比较运算符,或使用Python 2.7或3.2中提供的total_ordering decorator

+0

谢谢。已经完全忘记了total_ordering。这将完美地完成。 – 2012-04-07 13:54:11

+1

total_ordering适用于您的情况。但是,使用total_ordering的两个不同类可能会出错:http://bugs.python.org/issue10042 – 2012-04-08 08:01:33