2010-02-26 8 views
17

Khi so sánh một tuple với một danh sách như ...Python: Tại sao so sánh giữa các danh sách và bộ tuple không được hỗ trợ?

>>> [1,2,3] == (1,2,3) 
False 
>>> [1,2,3].__eq__((1,2,3)) 
NotImplemented 
>>> (1,2,3).__eq__([1,2,3]) 
NotImplemented 

... Python không sâu so sánh chúng như thực hiện với (1,2,3) == (1,2,3).

Vậy lý do cho điều này là gì? Có phải vì danh sách có thể thay đổi có thể thay đổi bất kỳ lúc nào (các vấn đề về an toàn luồng) hay không?

(Tôi biết nơi này được thực hiện trong CPython, vì vậy xin đừng trả lời nơi, nhưng tại sao nó được thực hiện.)

+4

Danh sách không phải là một bộ và ngược lại. Họ là những loại khác nhau. '[] ==()' sẽ trả về 'Sai'. – jathanism

+0

Xem thêm: http://stackoverflow.com/questions/12135264/what-are-the-best-ways-to-compare-the-contents-of-two-list-like-objects/12135322#12135322 – Erik

Trả lời

19

Bạn luôn có thể "đúc" nó

>>> tuple([1, 2]) == (1, 2) 
True 

Hãy nhớ rằng Python, không giống như Javascript ví dụ, is stronglytyped và một số (phần lớn?) Chúng tôi thích nó theo cách đó.

+2

Điều đó thực sự là cách tốt nhất. – jathanism

+2

Tôi thích nghĩ rằng hầu hết chúng ta đều thích nó theo cách đó. –

+0

Tôi nghĩ ý tưởng gõ mạnh là những gì thực sự quan trọng ở đây, vì vậy tôi sẽ chấp nhận câu trả lời của bạn là chính xác. – AndiDog

7

Không có lý do kỹ thuật nào cho các danh sách không thể so sánh với bộ dữ liệu; nó hoàn toàn là một quyết định thiết kế được thúc đẩy bởi ngữ nghĩa. Đối với giấy tờ chứng minh rằng nó không liên quan đến thread-an toàn, bạn có thể so sánh danh sách các danh sách khác:

>>> l1 = [1, 2, 3] 
>>> l2 = [1, 2, 3] 
>>> l1 == l2 
True 
>>> id(l1) == id(l2) 
False 

Có vẻ như hợp lý để cho phép người dùng trực tiếp so sánh danh sách và các bộ, nhưng sau đó bạn kết thúc với những câu hỏi khác: nên việc người dùng được phép so sánh danh sách và hàng đợi? Điều gì về bất kỳ hai đối tượng cung cấp vòng lặp? Điều gì về sau đây?

>>> s = set([('x', 1), ('y', 2)]) 
>>> d = dict(s) 
>>> s == d # This doesn't work 
False 

Nó có thể phức tạp khá nhanh chóng. Các nhà thiết kế ngôn ngữ đã nhận ra vấn đề và tránh nó bằng cách đơn giản ngăn các loại bộ sưu tập khác nhau so sánh trực tiếp với nhau .

Lưu ý rằng giải pháp đơn giản (để tạo danh sách mới từ bộ tuple và so sánh chúng) là dễ dàng nhưng không hiệu quả. Nếu bạn đang làm việc với số lượng lớn các mặt hàng, bạn nên sử dụng một số thứ như:

def compare_sequences(iter1, iter2): 
    iter1, iter2 = iter(iter1), iter(iter2) 
    for i1 in iter1: 
     try: 
      i2 = next(iter2) 
     except StopIteration: 
      return False 

     if i1 != i2: 
      return False 

    try: 
     i2 = next(iter2) 
    except StopIteration: 
     return True 

    return False 

Điều này có lợi thế là làm việc trên hai trình tự, với chi phí rõ ràng về độ phức tạp.


Tôi lưu ý có ngoại lệ đối với bộ và hàng rào. Và không có nghi ngờ một vài người khác tôi không biết. Các nhà thiết kế ngôn ngữ là những người theo chủ nghĩa thuần túy, ngoại trừ nơi nó trả tiền để thực tế.

+0

+1 Điểm rất tốt, cảm ơn! – AndiDog

+3

Để so sánh hai chuỗi, không cần phải nhảy qua các vòng lặp tiếp theo/StopIteration. tất cả (i1 == i2 cho i1, i2 trong itertools.izip_longest (iter1, iter2, fillvalue = object())) –