Operators and Expressions
Arithmetic, comparison, logical and bitwise operators, and the order in which Python evaluates them.
Expressions, operators and operands
An expression is any piece of code
that produces a value: 42, price,
price * 1.21 and len(name) > 3 are all
expressions. A statement, such as an assignment, does something; an
expression is something.
An operator is a symbol or keyword
that combines values into a new value, such as +,
< or and. The values it works on are
its operands. In
price * 1.21, the operator is * and the
operands are price and 1.21. Most
operators are binary (two operands); a few are
unary (one operand), such as the minus in
-price.
Arithmetic operators
+addition,-subtraction*multiplication/true division//floor division%modulo (remainder)**exponentiation (power)
print(7 + 2, 7 - 2, 7 * 2)
print(7 / 2)
print(7 // 2)
print(7 % 2)
print(2 ** 10)
print(2 * 3.0) # one float operand makes the result a float
9 5 14 3.5 3 1 1024 6.0
True division and floor division
/ is true division: it always returns
a float, even when the division comes out even, so
6 / 3 is 2.0.
Floor division with
// divides and then rounds down to the nearest
whole number. With two integers the result is an int;
if either operand is a float, the result is a float with
.0.
Modulo with % gives the
remainder that belongs to that floor division. The two always fit
together: (a // b) * b + a % b == a. The built-in
divmod(a, b) returns both at once.
minutes = 135
print(minutes // 60, "h", minutes % 60, "min")
print(divmod(135, 60))
print(6 / 3, 6 // 3, 7.5 // 2, 7.5 % 2)
print(14 % 2 == 0) # the usual test for an even number
2 h 15 min (2, 15) 2.0 2 3.0 1.5 True
Negative operands
"Round down" means toward negative infinity, not toward zero. That
makes a difference as soon as a negative number is involved:
-7 / 2 is -3.5, and rounding down gives
-4, not -3. The remainder follows from the
rule above, so it always has the same sign as the divisor (the
right-hand operand).
print(-7 // 2, -7 % 2) # -4 * 2 + 1 == -7
print(7 // -2, 7 % -2) # -4 * -2 + -1 == 7
print(-17 // 5, -17 % 5)
-4 1 -4 -1 -4 3
Unary operators
Unary - negates its operand, unary
+ leaves it unchanged, and ~ is bitwise
inversion (see bitwise operators).
Python has no ++ or -- operators:
x++ is a SyntaxError, and
++x is simply +(+x), which does not change
x.
balance = 50
print(-balance, +balance, --balance, ++balance)
print(balance)
-50 50 50 50 50
Comparison operators
== (equal), != (not equal),
<, <=, > and
>= compare two values and return a Boolean. Numbers
of different types compare by value, so 1 == 1.0 is
True. Ordering values that cannot be compared, such as
1 < "2", raises a TypeError.
Chained comparisons
Comparisons can be chained as in mathematics.
a < b < c means
a < b and b < c, except that b is
evaluated only once. Each comparison in the chain links only its two
neighbors.
temperature = 21
print(18 <= temperature <= 24)
print(1 < 2 > 1.5) # 1 < 2 and 2 > 1.5
print(3 == 3.0 == 3)
True True True
Logical operators
and, or and not combine
conditions. x and y is true only if both are true;
x or y is true if at least one is;
not x inverts a truth value. They work on any values,
not just Booleans: zero, empty strings, empty collections and
None count as false, everything else as true.
Short-circuit evaluation
Python evaluates and and or from left to
right and stops as soon as the outcome is certain. This is called
short-circuit evaluation. If the left operand of and is false, the whole
expression is false and the right operand is never evaluated. You
can use that to guard against an error:
stock = 0
# 100 / stock would raise ZeroDivisionError, but it never runs
print(stock > 0 and 100 / stock > 5)
False
A second consequence: and and or return
the operand that decided the result, not a new Boolean.
or returns the first true operand (or the last one, if
none is true); and returns the first false operand (or
the last one, if all are true). not always returns
True or False.
nickname = ""
print(nickname or "guest") # a common way to supply a default
print("Ada" or "guest")
print(3 and 5, 0 and 5)
print(not 0, not "Ada")
guest Ada 5 0 True False
Identity and membership
is versus ==
== asks "do these two have the same value?"
is asks "are these the same object?" — it compares
identities, like id(a) == id(b). Two separate lists
with the same contents are equal, but they are not the same object.
basket = ["apple", "pear"]
same_basket = basket
other_basket = ["apple", "pear"]
print(basket == other_basket, basket is other_basket)
print(basket is same_basket)
answer = None
print(answer is None, answer is not None)
True False True True False
Membership: in and not in
x in y tests whether y contains
x; not in is its opposite. For strings it
looks for a substring; for lists, tuples, sets and dictionaries it
looks for an element (for dictionaries: a key).
print("py" in "python")
print("Py" in "python") # case matters
print(3 in [1, 2, 3])
print("kiwi" not in ["apple", "pear"])
True False True True
Bitwise operators
A bitwise operator works on the individual bits of integers. They are used for flags, permissions, network masks and low-level protocols.
&AND: 1 where both bits are 1|OR: 1 where at least one bit is 1^XOR: 1 where the bits differ-
~NOT: inverts every bit;~xequals-x - 1 -
<<shift left:x << nequalsx * 2**n -
>>shift right:x >> nequalsx // 2**n
a = 0b1100 # 12
b = 0b1010 # 10
print(format(a & b, "04b"), a & b)
print(format(a | b, "04b"), a | b)
print(format(a ^ b, "04b"), a ^ b)
print(format(a << 2, "b"), a << 2)
print(format(a >> 2, "04b"), a >> 2)
print(~a)
1000 8 1110 14 0110 6 110000 48 0011 3 -13
format(x, "04b") shows a number in binary, padded with
zeros to four digits. Written one above the other, the first line is
easy to check: 1100 & 1010 keeps only the leftmost
bit, where both have a 1.
Augmented assignment
Augmented assignment
combines an operator with assignment: x += 1 works
roughly like x = x + 1. Every binary arithmetic and
bitwise operator has a form: +=, -=,
*=, /=, //=, %=,
**=, &=, |=,
^=, <<= and >>=.
visitors = 10
visitors += 5
visitors *= 2
visitors //= 4
print(visitors)
greeting = "Hello"
greeting += "!"
print(greeting)
7 Hello!
The name must already exist: total += 1 on an unknown
name raises a NameError, because Python has to read the
old value first.
For numbers and strings, which are immutable,
+= creates a new object and rebinds the name, exactly
like x = x + 1. A list, however, is changed in place by
+=, so every other name that refers to the same list
sees the change:
basket = ["apples", "pears"]
shared = basket # a second name for the same list
basket += ["plums"] # changes the list in place
print(shared)
basket = basket + ["kiwis"] # builds a new list and rebinds basket
print(shared)
print(basket)
['apples', 'pears', 'plums'] ['apples', 'pears', 'plums'] ['apples', 'pears', 'plums', 'kiwis']
Operator precedence
When an expression contains several operators, operator precedence decides which are applied first, just as multiplication comes before addition in arithmetic. From highest to lowest priority:
| Level | Operators | Meaning |
|---|---|---|
| 1 | ( ) |
parentheses: grouping |
| 2 |
x[i] f(x) x.attr
|
indexing, calls, attribute access |
| 3 | ** |
exponentiation |
| 4 | +x -x ~x |
unary plus, minus, bitwise NOT |
| 5 |
* / // %
|
multiplication, division, floor division, modulo |
| 6 | + - |
addition, subtraction |
| 7 | << >> |
bit shifts |
| 8 | & |
bitwise AND |
| 9 | ^ |
bitwise XOR |
| 10 | | |
bitwise OR |
| 11 |
== != <
<= > >=
is is not in
not in
|
comparisons, identity, membership |
| 12 | not |
logical NOT |
| 13 | and |
logical AND |
| 14 | or |
logical OR |
| 15 | x if c else y |
conditional expression |
Associativity
When operators of the same level meet,
associativity decides the order. Almost all binary
operators are left-associative: 10 - 4 - 3 is
(10 - 4) - 3. The exception is **, which
is right-associative: 2 ** 3 ** 2 is
2 ** (3 ** 2). Comparisons do not group at all; they
chain, as shown above.
** also binds more tightly than a unary minus on its
left, but less tightly than one on its right. So
-2 ** 2 is -(2 ** 2), while
2 ** -1 works as expected.
print(3 + 4 * 2 ** 2) # 3 + (4 * (2 ** 2))
print((3 + 4) * 2 ** 2)
print(10 - 4 - 3, 100 / 10 / 5)
print(2 ** 3 ** 2) # 2 ** 9
print(-2 ** 2, (-2) ** 2, 2 ** -1)
print(not 1 == 2) # not (1 == 2)
print(True or False and False) # True or (False and False)
19 28 3 2.0 512 -4 4 0.5 True True