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; ~x equals -x - 1
  • << shift left: x << n equals x * 2**n
  • >> shift right: x >> n equals x // 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