2013-04-05 24 views
8

Tôi đã sắp xếp một số mã thay crufty và đã xem qua các cấu trúc khá kỳ quặc sau:if (foo hoặc thanh hoặc baz) là None:

#!/usr/bin/env python2.7 
# ... 
if (opts.foo or opts.bar or opts.baz) is None: 
    # (actual option names changed to protect the guilty) 
    sys.stderr.write("Some error messages that these are required arguments") 

... và tôi đã tự hỏi nếu điều này sẽ không bao giờ làm cho bất kỳ ý nghĩa nào có thể hiểu được.

tôi đã thay đổi nó để cái gì đó như:

#!/usr/bin/env python2.7 
if None in (opts.foo, opts.bar, opts.baz): 
    # ... 

tôi đã cháy lên một thông dịch viên và thực sự thử xây dựng đầu tiên ... nó dường như chỉ có tác dụng nếu các giá trị đều sai cuối cùng các giá trị sai này là None. (Nói cách khác, việc triển khai CPython dường như trả lại giá trị sai thực sự hoặc giá trị cuối cùng đầu tiên từ một chuỗi các biểu thức hoặc).

tôi vẫn nghi ngờ rằng các mã đúng nên sử dụng một trong hai bất kỳ() hoặc tất cả() built-in đã được thêm 2,5 (mã trong câu hỏi đã đòi hỏi 2.7). Tôi chưa chắc chắn đó là ngữ nghĩa ưa thích/dự định khi tôi mới bắt đầu dự án này.

Vậy có trường hợp nào mã gốc này có ý nghĩa không?

+0

Đó là khủng khiếp. hãy cẩn thận bạn không giới thiệu một lỗi mới bằng cách sửa lỗi này :) –

Trả lời

5

Hành vi đoản mạch gây ra foo or bar or baz để trả về giá trị cuối cùng của ba giá trị boolean-true hoặc giá trị cuối cùng nếu tất cả là boolean-false. Vì vậy, về cơ bản nó có nghĩa là "nếu tất cả là sai và cuối cùng là Không".

Phiên bản đã thay đổi của bạn hơi khác. Ví dụ: if None in (opts.foo, opts.bar, opts.baz), nhập khối if nếu opts.foo là Không và hai còn lại là 1, trong khi phiên bản gốc sẽ không (vì None or 1 or 1 sẽ đánh giá là 1, không phải là Không). Phiên bản của bạn sẽ bước vào if khi bất kỳ của ba là Không, bất kể những gì hai người khác là, trong khi phiên bản gốc sẽ nhập if chỉ khi cuối cùng là Không hai người khác là bất kỳ boolean- giá trị sai.

Phiên bản nào bạn muốn tùy thuộc vào cách phần còn lại của mã được cấu trúc và giá trị nào có thể có (đặc biệt là chúng có giá trị boolean-false ngoài None, chẳng hạn như False hoặc 0 hoặc một chuỗi rỗng). Trực giác phiên bản của bạn có vẻ hợp lý hơn, nhưng nếu mã có các thủ thuật đặc biệt như thế này trong nó, bạn không bao giờ biết trường hợp góc nào có thể xuất hiện.

5

Nó hoạt động theo cách đó bởi vì or là một toán tử ngắn mạch, chi tiết có trong docs. Do đó, tuyên bố if đầu tiên của bạn bằng:

if opts.baz is None 

Chúng tôi có thể đoán tác giả của mã đó được mong đợi là gì. Tôi nghĩ rằng, như bạn đã đề cập, anh ta nghĩ đến việc sử dụng not all([opts.foo, opts.bar, opts.baz]).

+1

Để trả lời câu hỏi của mình cụ thể hơn: có vẻ như mã bị lỗi và tôi không thể nghĩ ra một trường hợp nào có ý nghĩa. – Anorov

+1

Sẽ có ý nghĩa nếu không có toán tử "is" ở đó. Nhưng đây là kỹ thuật thử nghiệm nếu tất cả các giá trị đánh giá sai * và * cuối cùng là, cụ thể, một tham chiếu đến None singleton. –

+0

@JimDennis Thật vậy – Anorov

0

Tôi muốn

if any(i is None for i in (opts.foo, opts.bar, opts.baz)) 

vì nó chính xác thể hiện mục tiêu dự định.

OTOH,

not all([opts.foo, opts.bar, opts.baz]) 

không kiểm tra sự sai lầm, không phải cho None.

Mã ban đầu dường như không có ý nghĩa; có vẻ như đã được viết bởi ai đó không biết họ đang làm gì.

0

hãy thử cả hai mã của bạn:

In [20]: foo = True 

In [22]: bar = None 

In [23]: baz = None 

In [24]: foo or bar or baz 
Out[24]: True 

In [25]: (foo or bar or baz) is None 
Out[25]: False 

In [28]: ((foo or bar or baz) is None) == (None in (foo, bar, baz)) 
Out[28]: False 

Bạn có thể thấy viết lại của bạn không giống như mã gốc.

điều kiện đầu tiên của bạn chỉ trả lại Đúng khi tất cả các biến của bạn là Không

In [19]: (None or None or None) is None 
Out[19]: True 

vì vậy bạn có thể viết lại điều kiện đầu tiên của bạn đến:

if foo == bar == bar == None: 
+0

Tôi thừa nhận rằng ngữ nghĩa là khác nhau; điểm ở đây là suy đoán xem liệu có bất kỳ trường hợp hợp lý nào cho ngữ nghĩa ban đầu là chính xác hay không. Tôi nghĩ rằng mã trước đó sẽ không thành công trong các trường hợp góc khác nhau, vui vẻ, dường như chưa bao giờ được ghi nhận trong thực tế. (Đó là một phần của tiện ích dòng lệnh nội bộ chỉ được sử dụng bởi rất ít nhân viên). –

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