2010-08-23 55 views
17

Có cách nào để kiểm tra xem hai đối tượng có cùng giá trị không, ngoài việc lặp qua các thuộc tính của chúng và so sánh các giá trị của chúng theo cách thủ công?So sánh hai đối tượng

+0

Xem [câu hỏi này tương tự] (http://stackoverflow.com/ câu hỏi/390250/thanh lịch-cách-to-hỗ trợ-tương đương-bình đẳng-in-python-lớp học) – GreenMatt

Trả lời

8

giải pháp @Joe Kington của hoạt động nếu có một __dict__ (một số đối tượng, trong đó có lệnh nội trú, không có một) và __eq__ công trình cho tất cả các giá trị của cả hai dicts (một nặng bằng văn bản __eq__ ngoại lệ mayraise vv). Nhưng nó là khủng khiếp unpythonic. Nó thậm chí không xử lý các loại phụ danh nghĩa đúng ... các kiểu con cấu trúc ít hơn nhiều (tức là các kiểu mà bạn có thể sử dụng tại chỗ/cho việc gõ vịt). Không làm điều này.

Nhưng thường thì bạn nên sử dụng phương pháp __eq__ được điều chỉnh thủ công chỉ so sánh một số thuộc tính quan trọng. Ví dụ. Hợp lý chỉ nên so sánh tử số và mẫu số, không gì hơn.

+2

"một số so sánh vô nghĩa có thể tăng ngoại lệ": không, điều này chỉ áp dụng cho các so sánh liên quan đến việc đặt hàng - kiểm tra nếu 'a' bằng' b' (tức là 'a == b', được biểu thị hoặc ngụ ý) ** không bao giờ ** ngoại lệ (trừ khi bạn cố tình mã một lớp lạ ghi đè '__eq__' cho mục đích duy nhất là gây ra các ngoại lệ như vậy ;-). IOW, so sánh về bình đẳng/bất bình đẳng là ** không bao giờ ** "vô nghĩa". –

+0

@Alex Hoặc trừ khi ai đó mã hóa một lớp như vậy. Các lớp học được viết kém sẽ xảy ra khá thường xuyên. Tuy nhiên, delnan dường như ngụ ý rằng một số loại nội trang đã xử lý theo cách này, điều này thực sự không chính xác. –

+0

Có, nội trang không làm điều này. Xin lỗi nếu nó đọc như thế. – delnan

-4

object1.__dict__ == object2.__dict__ nên được tất cả các bạn cần, tôi nghĩ ...

Edit: vars(object1) == vars(object2) có lẽ là pythonic hơn một chút, mặc dù @delnan làm cho một điểm hợp lệ về các đối tượng (ví dụ int s) mà không có một __dict__. Tôi không đồng ý rằng một tùy chỉnh __eq__ là một cách tiếp cận tốt hơn cho các trường hợp đơn giản, mặc dù ... Đôi khi nó không có giá trị nỗ lực để đi xa nhanh chóng và bẩn, nếu nhanh chóng và bẩn hoàn toàn làm những gì bạn cần, i.m.h.o.

+8

Chạm vào '__dict__' trực tiếp về cơ bản là luôn luôn sai. – habnabit

+2

@Aaron, tôi đồng ý rằng việc sửa đổi '__dict__' trực tiếp về cơ bản luôn sai ... Tôi không đồng ý rằng đọc nó trực tiếp về cơ bản là luôn luôn sai. Có lẽ 'vars' là một chút rõ ràng hơn, mặc dù ... –

+3

không, đọc nó về cơ bản luôn luôn là sai là tốt. Nó bỏ qua giao thức mô tả, chưa kể nó dựa trên một chi tiết thực hiện. – habnabit

6

Để nói thêm về câu trả lời của delnan:

_NOTFOUND = object() 

class Rational(object): 
    def __eq__(self, other): 
     for attr in ['numerator', 'denominator']: 
      v1, v2 = [getattr(obj, attr, _NOTFOUND) for obj in [self, other]] 
      if v1 is _NOTFOUND or v2 is _NOTFOUND: 
       return False 
      elif v1 != v2: 
       return False 
     return True 
2

Bạn có thể so sánh namedtuple trực tiếp.
Nếu không, bạn phải xác định một trong hai so sánh của riêng bạn giàu __eq__ và có thể __ne__
hoặc riêng __cmp__

bạn thấy datamodel để biết thêm