2011-08-22 29 views
45

Phương thức nào cần được ghi đè/triển khai khi tạo các lớp do người dùng định nghĩa và/hoặc có thể băm trong python?Tạo một lớp python do người dùng định nghĩa có thể sắp xếp, có thể bẻ khóa

Bạn cần phải chú ý điều gì?

Tôi nhập dir({}) vào thông dịch viên của mình để có danh sách các phương pháp được xây dựng trong dicts. Trong số đó, tôi giả sử tôi cần một số người thực hiện một số tập hợp con của

['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__'] 

Có sự khác biệt nào về phương pháp nào được thực hiện cho Python3 trái ngược với Python2 không?

+3

Thảo luận tốt tại đây: http://stackoverflow.com/q/1061283/641766. Sự khác biệt giữa Python 2.x và 3.x là '__cmp__' đã bị xóa. – zeekay

Trả lời

51

Tôi gần như đăng bài này như là một bình luận cho các câu trả lời khác nhưng nó thực sự là một câu trả lời trong và của chính nó.

Để làm cho các mục của bạn có thể sắp xếp, chúng chỉ cần triển khai __lt__. Đó là phương pháp duy nhất được sử dụng bởi loại được xây dựng.

Các so sánh khác hoặc functools.total_ordering chỉ cần thiết nếu bạn thực sự muốn sử dụng toán tử so sánh với lớp của mình.

Để làm cho các mục của bạn có thể băm, bạn triển khai __hash__ như những người khác đã lưu ý. Bạn cũng nên triển khai __eq__ theo cách tương thích - các mục tương đương phải băm giống nhau.

+0

vì vậy việc triển khai nghèo '__lt__' có thể khiến python sắp xếp không thể đoán trước? (ví dụ, nếu x .__ lt __ (y) và y .__ lt __ (x)) –

+3

Tôi không biết về "không thể đoán trước", nó sẽ nhất quán nếu nạp cùng một đầu vào giống nhau, nhưng một thứ tự đầu vào khác nhau có thể gây ra khác nhau các mục sẽ theo thứ tự khác. Có, nếu bạn thực hiện không đúng so sánh được sử dụng để sắp xếp, Python sẽ sắp xếp không đúng cách. Tôi muốn giới thiệu một hàm '__key__' để biến thể hiện thành một tuple, sau đó chỉ cần có cả' __lt__' ('self .__ key __() agf

2

Có một vài cách để đánh dấu đối tượng của bạn có thể sắp xếp. so sánh phong phú, xác định bởi một tập hợp các hàm - Thứ nhất:

object.__lt__(self, other) 
object.__le__(self, other) 
object.__eq__(self, other) 
object.__ne__(self, other) 
object.__gt__(self, other) 
object.__ge__(self, other) 

Ngoài ra nó có thể xác định chỉ có một chức năng:

object.__cmp__(self, other) 

Và cuối cùng cần được xác định nếu bạn muốn xác định __hash__ chức năng tùy chỉnh . Xem doc.

+1

Trong Python 3, "[...] phương thức đặc biệt' __cmp __() 'không còn được hỗ trợ," xem [phần có liên quan ở đây] (https://docs.python.org/release/3.0.1/whatsnew /3.0.html#ordering-comparisons). –

10

Không có bất kỳ sự khác biệt giữa Python 2 và 3.

Đối sortability:

Bạn nên xác định phương pháp so sánh. Điều này làm cho các mục của bạn có thể sắp xếp. Nói chung, bạn không nên thích __cmp__().

Tôi thường sử dụng functools.total_ordering trang trí.

functools.total_ordering (cls) Cho một lớp xác định một hoặc nhiều phương thức đặt hàng so sánh, trang trí lớp này cung cấp phần còn lại. này đơn giản hóa các nỗ lực tham gia vào việc xác định tất cả các khả năng hoạt động so sánh giàu:

Lớp phải xác định một trong những __lt__(), __le__(), __gt__(), hoặc __ge__(). Ngoài ra, lớp học nên cung cấp phương thức __eq__().

Bạn nên cẩn thận với các phương pháp so sánh của mình để có phản ứng phụ. Bạn không muốn lớp học của bạn thay đổi khi so sánh.

Đối băm:

Bạn nên thực hiện phương pháp __hash__(). Tôi nghĩ cách tốt nhất là trả lại hash(repr(self)), vì vậy, băm của bạn sẽ là duy nhất.

+0

Để biết ví dụ về 'functools.total_ordering' từ tài liệu, hãy xem [tại đây] (https://docs.python.org/2/library/functools.html#functools.total_ordering). –

0

Thực hiện phương thức __lt__(self,other) là câu trả lời để làm cho lớp của bạn có thể sắp xếp được.
Nó có thể được sử dụng không chỉ cho phương pháp tích hợp sorted(iterable), mà còn xếp hàng ưu tiên thông qua mô-đun heapq.

Ngoài ra, tôi không thích thiết kế của python, rất nhiều phương pháp '__ge__', '__gt__', '__le__', '__lt__', '__ne__'không trực quan ở tất cả!
Ngược lại, Java Interface Comparable<T> (xem java doc) trả về số nguyên âm, số không hoặc số nguyên dương vì đối tượng này nhỏ hơn hoặc bằng lớn hơn đối tượng được chỉ định, là trực tiếp và thân thiện!

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