Answer 557d6f2fe0a3006892000915 number % 2 == 0 is a valid boolean expression that checks whether number % 2 is equivalent to 0 . For even number s, the result is the value, True . But, number 2% == 0 is not a valid expression, because % == is not a valid operator. Submitted by Glenn Richard.
Falsy values are values that evaluate to False in a boolean context. Falsy values include empty sequences (lists, tuples, strings, dictionaries, sets), zero in every numeric type, None , and False .
Python returns the first character of a string when either of these are used as index values. 0 and -0 are the same.
Python assigns boolean values to values of other types. For numerical types like integers and floating-points, zero values are false and non-zero values are true.
The first two expressions both parse as tuples:
(0, 0) == 0
(which is False
), followed by 0
0
, followed by 0 == (0, 0)
(which is still False
that way around).The expressions are split that way because of the relative precedence of the comma separator compared to the equality operator: Python sees a tuple containing two expressions, one of which happens to be an equality test, instead of an equality test between two tuples.
But in your second set of statements, a = 0, 0
cannot be a tuple. A tuple is a collection of values, and unlike an equality test, assignment has no value in Python. An assignment is not an expression, but a statement; it does not have a value that can be included into a tuple or any other surrounding expression. If you tried something like (a = 0), 0
in order to force interpretation as a tuple, you would get a syntax error. That leaves the assignment of a tuple to a variable – which could be made more explicit by writing it a = (0, 0)
– as the only valid interpretation of a = 0, 0
.
So even without the parentheses on the assignment to a
, both it and b
get assigned the value (0,0)
, so a == b
is therefore True
.
What you see in all 3 instances is a consequence of the grammar specification of the language, and how tokens encountered in the source code are parsed to generate the parse tree.
Taking a look at this low level code should help you understand what happens under the hood. We can take these python statements, convert them into byte code and then decompile them using the dis
module:
Case 1: (0, 0) == 0, 0
>>> dis.dis(compile("(0, 0) == 0, 0", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 0 (0)
6 COMPARE_OP 2 (==)
9 LOAD_CONST 0 (0)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
(0, 0)
is first compared to 0
first and evaluated to False
. A tuple is then constructed with this result and last 0
, so you get (False, 0)
.
Case 2: 0, 0 == (0, 0)
>>> dis.dis(compile("0, 0 == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 0 (0)
3 LOAD_CONST 0 (0)
6 LOAD_CONST 2 ((0, 0))
9 COMPARE_OP 2 (==)
12 BUILD_TUPLE 2
15 POP_TOP
16 LOAD_CONST 1 (None)
19 RETURN_VALUE
A tuple is constructed with 0
as the first element. For the second element, the same check is done as in the first case and evaluated to False
, so you get (0, False)
.
Case 3: (0, 0) == (0, 0)
>>> dis.dis(compile("(0, 0) == (0, 0)", '', 'exec'))
1 0 LOAD_CONST 2 ((0, 0))
3 LOAD_CONST 3 ((0, 0))
6 COMPARE_OP 2 (==)
9 POP_TOP
10 LOAD_CONST 1 (None)
13 RETURN_VALUE
Here, as you see, you're just comparing those two (0, 0)
tuples and returning True
.
Another way to explain the problem: You're probably familiar with dictionary literals
{ "a": 1, "b": 2, "c": 3 }
and array literals
[ "a", "b", "c" ]
and tuple literals
( 1, 2, 3 )
but what you don't realize is that, unlike dictionary and array literals, the parentheses you usually see around a tuple literal are not part of the literal syntax. The literal syntax for tuples is just a sequence of expressions separated by commas:
1, 2, 3
(an "exprlist" in the language of the formal grammar for Python).
Now, what do you expect the array literal
[ 0, 0 == (0, 0) ]
to evaluate to? That probably looks a lot more like it should be the same as
[ 0, (0 == (0, 0)) ]
which of course evaluates to [0, False]
. Similarly, with an explicitly parenthesized tuple literal
( 0, 0 == (0, 0) )
it's not surprising to get (0, False)
. But the parentheses are optional;
0, 0 == (0, 0)
is the same thing. And that's why you get (0, False)
.
If you're wondering why the parentheses around a tuple literal are optional, it is largely because it would be annoying to have to write destructuring assignments that way:
(a, b) = (c, d) # meh
a, b = c, d # better
Adding a couple of parentheses around the order in which actions are performed might help you understand the results better:
# Build two element tuple comprising of
# (0, 0) == 0 result and 0
>>> ((0, 0) == 0), 0
(False, 0)
# Build two element tuple comprising of
# 0 and result of (0, 0) == 0
>>> 0, (0 == (0, 0))
(0, False)
# Create two tuples with elements (0, 0)
# and compare them
>>> (0, 0) == (0, 0)
True
The comma is used to to separate expressions (using parentheses we can force different behavior, of course). When viewing the snippets you listed, the comma ,
will separate it and define what expressions will get evaluated:
(0, 0) == 0 , 0
#-----------|------
expr 1 expr2
The tuple (0, 0)
can also be broken down in a similar way. The comma separates two expressions comprising of the literals 0
.
In the first one Python is making a tuple of two things:
(0, 0) == 0
, which evaluates to False
0
In the second one it's the other way around.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With