Python Operator Precedence

Python operator precedence is one of those topics that looks simple on the surface but quietly causes bugs in code that seems correct at first glance. When you write an expression like 3 + 4 * 2, Python does not just read it left to right — it applies rules that determine which operations happen first. Understanding python operator precedence lets you write expressions that do exactly what you intend, without relying on guesswork or excessive parentheses.

This guide walks through every level of Python's precedence hierarchy, explains the associativity rules that govern how same-precedence operators are grouped, and shows practical examples of what happens when precedence works in surprising ways.

What Is Operator Precedence in Python

Operator precedence in Python refers to the set of rules that determine which operator gets evaluated first when an expression contains multiple operators. Python evaluates higher-precedence operators before lower-precedence ones, regardless of their position in the expression.

You may already be familiar with this from basic math — multiplication happens before addition. Python follows the same principle, but extends it to cover dozens of operators: arithmetic, comparison, logical, bitwise, and more.

Here is a simple example that shows python operator precedence at work:

result = 2 + 3 * 4
print(result)
Output
14

Even though the + appears first in the expression, Python evaluates 3 * 4 first because multiplication has higher precedence than addition. The result is 2 + 12, which gives 14, not 20.

Python Operator Precedence Table

Python defines a clear hierarchy for its operators. The table below lists operator groups from highest precedence (evaluated first) to lowest precedence (evaluated last):

PrecedenceOperatorDescription
1 (highest)()Parentheses
2**Exponentiation
3+x, -x, ~xUnary plus, unary minus, bitwise NOT
4*, /, //, %Multiplication, division, floor division, modulo
5+, -Addition, subtraction
6<<, >>Bitwise shift operators
7&Bitwise AND
8^Bitwise XOR
9|Bitwise OR
10==, !=, >, <, >=, <=, is, is not, in, not inComparisons, identity, membership
11notLogical NOT
12andLogical AND
13 (lowest)orLogical OR

This table is your reference point every time you write a complex expression. Python's official documentation maintains the full operator precedence table if you want to cross-reference it.

Arithmetic Operator Precedence

Arithmetic operators follow the familiar PEMDAS-style rules from mathematics. Exponentiation comes before multiplication and division, which come before addition and subtraction.

a = 2 + 3 ** 2
b = 10 - 4 / 2
c = 5 * 3 + 8 // 3

print(a)
print(b)
print(c)
Output
11
8.0
17

In the first expression, 3 ** 2 is evaluated first (giving 9), then 2 + 9 gives 11. In the second, 4 / 2 is evaluated first (giving 2.0), then 10 - 2.0 gives 8.0. In the third, 5 * 3 gives 15 and 8 // 3 gives 2, then 15 + 2 gives 17.

Exponentiation deserves special attention because it has the highest precedence among arithmetic operators:

import math

x = -2 ** 2
y = (-2) ** 2

print(x)
print(y)
Output
-4
4

This is a common source of confusion. In x = -2 ** 2, Python first applies the exponentiation 2 ** 2 = 4, then applies the unary minus to get -4. The - here is treated as a unary operator applied after the exponentiation. Adding parentheses as in (-2) ** 2 forces the minus to bind to 2 first, producing 4.

Comparison Operators and Chaining

Comparison operators in Python all sit at the same precedence level. What makes them unique in Python is that they support chaining — you can write expressions like 1 < x < 10 and Python evaluates them correctly.

x = 5

result1 = 1 < x < 10
result2 = x > 3 and x < 8
result3 = 2 + 3 == 5

print(result1)
print(result2)
print(result3)
Output
True
True
True

In 1 < x < 10, Python evaluates it as (1 < x) and (x < 10). This chaining behavior is built into the language and is a clean, readable feature that many other languages do not support.

Notice that 2 + 3 == 5 works correctly because + has higher precedence than ==. Python computes 2 + 3 = 5 first, then compares 5 == 5.

Logical Operators Precedence

Logical operators follow a clear order: not is evaluated before and, which is evaluated before or. This is critical to understand when writing conditions.

a = True
b = False
c = True

result1 = a or b and c
result2 = (a or b) and c
result3 = not a or b

print(result1)
print(result2)
print(result3)
Output
True
True
False

In a or b and c, Python evaluates b and c first (because and has higher precedence than or), giving False and True = False, then True or False = True.

In not a or b, Python evaluates not a first (unary not has highest logical precedence), giving not True = False, then False or False = False.

These differences can completely change your program's logic if you do not account for them.

Mixing Arithmetic and Logical Operators

Real-world Python code often mixes arithmetic, comparison, and logical operators in the same expression. Python's precedence rules handle this consistently, evaluating arithmetic first, then comparisons, then logical operators.

score = 75
passing = score >= 60 and score <= 100

age = 20
eligible = age >= 18 and age * 2 < 100

print(passing)
print(eligible)
Output
True
True

In score >= 60 and score <= 100, Python evaluates both comparison expressions first (score >= 60 is True, score <= 100 is True), then combines them with and.

In age * 2 < 100, Python evaluates age * 2 = 40 first, then 40 < 100 = True, then combines with age >= 18 using and.

Bitwise Operators Precedence

Bitwise operators work on the binary representations of integers. Their precedence sits between arithmetic operators and comparison operators, with the following order from highest to lowest: ~ (NOT), then << and >> (shifts), then & (AND), then ^ (XOR), then | (OR).

a = 0b1100  # 12
b = 0b1010  # 10

result1 = a & b
result2 = a | b
result3 = a ^ b
result4 = a >> 1

print(bin(result1))
print(bin(result2))
print(bin(result3))
print(bin(result4))
Output
0b1000
0b1110
0b110
0b110

The & operation performs a bitwise AND on each bit position. The | performs a bitwise OR. The ^ performs XOR (exclusive OR). The >> right-shift moves all bits one position to the right, which is equivalent to integer division by 2.

When mixing bitwise and arithmetic operators, be aware that arithmetic has higher precedence than bitwise shifts, which have higher precedence than &, ^, and |:

x = 4 + 2 << 1
y = 4 + (2 << 1)
z = (4 + 2) << 1

print(x)
print(y)
print(z)
Output
12
8
12

In 4 + 2 << 1, Python evaluates 4 + 2 = 6 first (addition before shift), then 6 << 1 = 12. The parenthesized versions make the evaluation order explicit.

Associativity: Left vs Right

When two operators have the same precedence level, Python uses associativity rules to decide the evaluation order. Most operators in Python are left-associative, meaning expressions are evaluated left to right. The only right-associative operator is exponentiation (**).

Left-associativity example:

result = 20 - 5 - 3
print(result)
Output
12

Because - is left-associative, Python evaluates (20 - 5) - 3 = 15 - 3 = 12. If it were right-associative, it would compute 20 - (5 - 3) = 20 - 2 = 18, which is different.

Right-associativity with exponentiation:

result = 2 ** 3 ** 2
print(result)
Output
512

Because ** is right-associative, Python evaluates 3 ** 2 = 9 first, then 2 ** 9 = 512. If it were left-associative, it would compute (2 ** 3) ** 2 = 8 ** 2 = 64. The right-to-left rule for exponentiation follows standard mathematical convention.

Using Parentheses to Control Precedence

Parentheses always have the highest precedence in Python. Wrapping any part of an expression in parentheses forces it to be evaluated first, regardless of the operators inside. This is the most reliable way to ensure your expressions evaluate exactly as intended.

a = (2 + 3) * 4
b = 2 + 3 * 4
c = (10 - 2) ** (1 + 1)
d = not (True or False)

print(a)
print(b)
print(c)
print(d)
Output
20
14
64
False

Using parentheses is also good practice for readability, even when they are not strictly required. If an expression is complex enough that a reader might be unsure of the evaluation order, adding parentheses clarifies your intent without changing functionality.

Walrus Operator and Assignment Expressions

Python 3.8 introduced the walrus operator :=, which assigns a value and returns it within an expression. It has very low precedence — lower than most operators, but higher than the comma.

import re

data = "Score: 95"
if match := re.search(r'\d+', data):
    value = int(match.group())
    doubled = value * 2
    print(doubled)
Output
190

The walrus operator allows the assignment and the condition check to happen together. Because := has low precedence, the right-hand expression is fully evaluated before the assignment occurs. You can read more about its behavior in the walrus operator documentation.

Common Precedence Mistakes

Understanding where mistakes commonly occur helps you avoid them in your own code.

Mistake 1 — Confusing not with low arithmetic precedence:

x = 5

wrong = not x == 5
correct = (not x) == 5

print(wrong)
print(correct)
Output
False
False

In not x == 5, comparison x == 5 is evaluated first (comparison beats not), giving not True = False. In (not x) == 5, not x gives not 5 = False (since 5 is truthy), then False == 5 = False. Both return False here, but for different reasons — and with different values of x, they diverge.

Mistake 2 — Assuming or and and have equal precedence:

flag = False or True and False
print(flag)
Output
False

Because and binds tighter than or, Python evaluates True and False = False first, then False or False = False. If both had equal precedence and evaluated left-to-right, False or True would give True, then True and False would give False — the same result here, but different in other cases.

Complete Working Example

This example pulls together arithmetic, comparison, logical, and bitwise operators in a real calculation, demonstrating how python operator precedence controls the flow from start to finish.

def evaluate_expression_demo():
    # Arithmetic with exponentiation and floor division
    base = 2 ** 4 + 10 // 3
    print(f"2 ** 4 + 10 // 3 = {base}")

    # Unary minus and exponentiation order
    neg_exp = -3 ** 2
    neg_exp_paren = (-3) ** 2
    print(f"-3 ** 2 = {neg_exp}")
    print(f"(-3) ** 2 = {neg_exp_paren}")

    # Mixed arithmetic and comparison
    score = 82
    grade_a = score >= 90
    grade_b = score >= 80 and score < 90
    print(f"Grade A: {grade_a}")
    print(f"Grade B: {grade_b}")

    # Logical precedence: and before or
    is_weekend = False
    is_holiday = True
    has_task = True
    day_off = is_weekend or is_holiday and not has_task
    print(f"Day off: {day_off}")

    # Bitwise operators
    flags = 0b1010
    mask = 0b1100
    result = flags & mask | (flags ^ mask) >> 1
    print(f"Bitwise result: {bin(result)}")

    # Associativity: right-associative exponentiation
    tower = 2 ** 3 ** 2
    print(f"2 ** 3 ** 2 (right-assoc): {tower}")

    # Parentheses forcing evaluation order
    forced = (2 + 3) * (4 - 1) ** 2
    natural = 2 + 3 * 4 - 1 ** 2
    print(f"(2 + 3) * (4 - 1) ** 2 = {forced}")
    print(f"2 + 3 * 4 - 1 ** 2 = {natural}")

evaluate_expression_demo()
Output
2 ** 4 + 10 // 3 = 19
-3 ** 2 = -9
(-3) ** 2 = 9
Grade A: False
Grade B: True
Day off: False
Bitwise result: 0b1011
2 ** 3 ** 2 (right-assoc): 512
(2 + 3) * (4 - 1) ** 2 = 45
2 + 3 * 4 - 1 ** 2 = 13

This example demonstrates every major precedence rule: exponentiation before addition, unary minus applied after exponentiation, arithmetic evaluated before comparison, and evaluated before or, not before and, right-associativity of **, and parentheses overriding everything. Refer back to the Python language reference for the authoritative precedence table whenever you write complex expressions.