2012-04-07 27 views
5

Trong the manual là nói:Phương pháp tối thiểu cho đặt hàng với Duck Typing bằng Python 3.1

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

Nhưng tôi thấy lỗi:

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

khi tôi chạy thử nghiệm này:

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 

Tôi ngạc nhiên khi IntVar() ở bên phải, __int__() không được gọi. Tôi đang làm gì sai?

Thêm __gt__() bản sửa lỗi này, nhưng có nghĩa là tôi không hiểu những gì các yêu cầu tối thiểu là để đặt hàng ...

Cảm ơn, Andrew

+0

Nếu bạn xem [tài liệu phương pháp so sánh phong phú] (http://docs.python.org/release/3.1.3/reference/datamodel.html#object.__lt__), nó đề cập cụ thể đến hành vi này - 'Có không có phiên bản đối số hoán đổi của các phương thức này (được sử dụng khi đối số bên trái không hỗ trợ hoạt động nhưng đối số phải làm); thay vào đó, __lt __() và __gt __() là sự phản ánh của nhau, __le __() và __ge __() là sự phản ánh của nhau, và __eq __() và __ne __() là sự phản ánh của chúng. Đối số cho các phương pháp so sánh phong phú không bao giờ bị ép buộc.' – agf

+0

@agf: Câu trả lời phải nằm trong Câu trả lời, không có trong nhận xét. –

+0

@EthanFurman Các tài liệu không hướng dẫn bạn mặc dù trường hợp cụ thể như câu trả lời của Sven, và IMO đó là cần thiết để công nhận việc đăng bài như một câu trả lời không chỉ là một bình luận. – agf

Trả lời

4

Python 3.x sẽ không bao giờ làm bất cứ coercions kiểu cho các nhà khai thác , do đó, __int__() không được sử dụng trong ngữ cảnh này. Việc so sánh

a < b 

đầu tiên sẽ cố gắng gọi type(a).__lt__(a, b), và nếu điều này trở NotImplemented, nó sẽ gọi type(b).__gt__(b, a).

Trích dẫn từ tài liệu hướng dẫn về việc so sánh hoạt động cho một loại duy nhất và giải thích ở trên cho thấy lý do tại sao điều này là đủ cho một loại duy nhất.

Để làm cho loại của bạn tương tác chính xác với int, bạn nên triển khai tất cả toán tử so sánh hoặc sử dụng total_ordering decorator có sẵn bằng Python 2.7 hoặc 3.2.

+0

cảm ơn. đã hoàn toàn quên về total_ordering. điều đó sẽ làm hoàn hảo. –

+1

total_ordering hoạt động trong trường hợp của bạn. Tuy nhiên, hai lớp khác nhau sử dụng total_ordering có thể bị lỗi: http://bugs.python.org/issue10042 –

Các vấn đề liên quan