Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
801 views
in Technique[技术] by (71.8m points)

boolean - Python's in (__contains__) operator returns a bool whose value is neither True nor False

As expected, 1 is not contained by the empty tuple

>>> 1 in ()
False

but the False value returned is not equal to False

>>> 1 in () == False
False

Looking at it another way, the in operator returns a bool which is neither True nor False:

>>> type(1 in ())
<type 'bool'>
>>> 1 in () == True, 1 in () == False
(False, False)

However, normal behaviour resumes if the original expression is parenthesized

>>> (1 in ()) == False
True

or its value is stored in a variable

>>> value = 1 in ()
>>> value == False
True

This behaviour is observed in both Python 2 and Python 3.

Can you explain what is going on?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You are running into comparison operator chaining; 1 in () == False does not mean (1 in ()) == False.

Rather, comparisons are chained and the expression really means:

(1 in ()) and (() == False)

Because (1 in ()) is already false, the second half of the chained expression is ignored altogether (since False and something_else returns False whatever the value of something_else would be).

See the comparisons expressions documentation:

Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

For the record, <, >, ==, >=, <=, !=, is, is not, in and not in are all comparison operators (as is the deprecated <>).

In general, don't compare against booleans; just test the expression itself. If you have to test against a boolean literal, at least use parenthesis and the is operator, True and False are singletons, just like None:

>>> (1 in ()) is False
True

This gets more confusing still when integers are involved. The Python bool type is a subclass of int1. As such, False == 0 is true, as is True == 1. You therefor can conceivably create chained operations that almost look sane:

3 > 1 == True

is true because 3 > 1 and 1 == True are both true. But the expression:

3 > 2 == True

is false, because 2 == True is false.

1 bool is a subclass of int for historic reasons; Python didn't always have a bool type and overloaded integers with boolean meaning just like C does. Making bool a subclass kept older code working.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...