2012-04-02 34 views
21

tôi tự hỏi về việc sử dụng == khi so sánh hai máy phát điệnSo sánh hai máy phát điện bằng Python

Ví dụ:

x = ['1','2','3','4','5'] 

gen_1 = (int(ele) for ele in x) 
gen_2 = (int(ele) for ele in x) 

gen_1gen_2 là như nhau cho tất cả các mục đích thực tế, và nhưng khi tôi so sánh chúng:

>>> gen_1 == gen_2 
False 

Tôi đoán ở đây là == đây được đối xử như is thường lệ là, và kể từ gen_1gen_2 được đặt tại nhiều nơi khác nhau trong bộ nhớ:

>>> gen_1 
<generator object <genexpr> at 0x01E8BAA8> 
>>> gen_2 
<generator object <genexpr> at 0x01EEE4B8> 

so sánh của họ để đánh giá False. Tôi có đúng với dự đoán này không? Và bất kỳ cái nhìn sâu sắc khác được chào đón.

Và btw, tôi biết làm thế nào để so sánh hai máy phát điện:

>>> all(a == b for a,b in zip(gen_1, gen_2)) 
True 

hoặc thậm chí

>>> list(gen_1) == list(gen_2) 
True 

Nhưng nếu có một cách tốt hơn, tôi rất muốn biết.

+5

Hãy suy nghĩ về biểu thức trình tạo giống như một hàm, không giống như danh sách. – agf

+1

khi bạn so sánh các máy phát, bạn xả chúng và sau đó chúng trở nên trống rỗng –

Trả lời

12

Bạn đúng với dự đoán của mình - dự phòng để so sánh các loại không xác định == là so sánh dựa trên nhận dạng đối tượng.

Cách tốt hơn để so sánh các giá trị mà họ tạo ra sẽ là

from itertools import izip_longest, tee 
sentinel = object() 
all(a == b for a, b in izip_longest(gen_1, gen_2, fillvalue=sentinel)) 

này có thể thực sự ngắn mạch mà không nhất thiết phải xem xét tất cả các giá trị. Như đã chỉ ra bởi larsmans trong các bình luận, chúng ta không thể sử dụng izip() ở đây vì nó có thể cho kết quả sai nếu các máy tạo ra một số nguyên tố khác nhau - izip() sẽ dừng trên trình lặp ngắn nhất. Chúng tôi sử dụng một ví dụ object mới được tạo làm giá trị điền cho izip_longest(), vì object trường hợp cũng được so sánh theo nhận dạng đối tượng, do đó, sentinel được đảm bảo để so sánh bất bình đẳng với mọi thứ khác.

Lưu ý rằng không có cách nào so sánh trình tạo mà không thay đổi trạng thái của chúng. Bạn có thể lưu trữ các mục đã được tiêu thụ nếu bạn cần chúng sau này:

gen_1, gen_1_teed = tee(gen_1) 
gen_2, gen_2_teed = tee(gen_2) 
all(a == b for a, b in izip_longest(gen_1, gen_2, fillvalue=sentinel)) 

này sẽ cung cấp rời khỏi tình trạng gen_1gen_2 về cơ bản không thay đổi.Tất cả các giá trị được tiêu thụ bởi all() được lưu trữ bên trong đối tượng tee.

Tại thời điểm đó, bạn có thể tự hỏi mình có thực sự sử dụng máy phát điện lười biếng cho ứng dụng hay không - có thể tốt hơn là chỉ chuyển đổi chúng sang danh sách và làm việc với danh sách thay thế.

+0

'izip' có cùng vấn đề với' zip': nó không thành công khi máy phát không tạo ra số lượng mục tương đương. –

+0

@larsmans: Cảm ơn, tôi vừa để ý! –

+0

Cảm ơn rất nhiều Sven! – Akavall

7

Vì máy phát điện tạo ra giá trị theo yêu cầu, không có cách nào "so sánh" chúng mà không thực sự tiêu thụ chúng. Và nếu máy phát điện của bạn tạo ra một chuỗi các giá trị vô hạn, thì thử nghiệm bình đẳng như bạn đề xuất sẽ vô dụng.

4

Để thực hiện so sánh mặt hàng của hai máy phát điện như với danh sách và các vùng chứa khác, Python sẽ phải tiêu thụ chúng hoàn toàn (tốt, ngắn hơn, dù sao). Tôi nghĩ tốt là bạn phải làm điều này một cách rõ ràng, đặc biệt là vì cái này hay cái kia có thể là vô hạn.

5

== thực sự giống như is trên hai máy phát, vì đó là séc duy nhất có thể được thực hiện mà không thay đổi trạng thái của chúng và do đó làm mất các phần tử.

list(gen_1) == list(gen_2) 

là cách đáng tin cậy và tổng quát khi so sánh hai trình tạo hữu hạn (nhưng rõ ràng là tiêu thụ cả hai); zip giải pháp dựa trên của bạn bị lỗi khi họ không tạo ra một số lượng bằng nhau của các yếu tố:

>>> list(zip([1,2,3,4], [1,2,3])) 
[(1, 1), (2, 2), (3, 3)] 
>>> all(a == b for a, b in zip([1,2,3,4], [1,2,3])) 
True 

Các giải pháp dựa trên list vẫn thất bại khi một trong hai máy phát điện tạo ra một số lượng vô hạn của các yếu tố. Bạn có thể đưa ra cách giải quyết cho điều đó, nhưng khi cả hai máy phát đều vô hạn, bạn chỉ có thể tạo ra một semi-algorithm vì không bình đẳng.

+0

Cảm ơn bạn đã chỉ ra sai lầm trong giải pháp dựa trên zip của mình. – Akavall