Python Operators — Arithmetic, Comparison, Logical, and Bitwise Guide

Sanjeev SharmaSanjeev Sharma
6 min read

Advertisement

Introduction

Why This Matters

Operators are the fundamental building blocks of expressions in Python. Every calculation, comparison, and logical decision in your code relies on operators. While basic arithmetic is obvious, Python has a rich set of operators — bitwise, identity, membership, and the walrus operator — that are powerful but often misunderstood.

Understanding operator precedence prevents subtle bugs where expressions evaluate in an unexpected order. Knowing the difference between == and is, or between and and &, is essential for writing correct Python. These distinctions are also common interview topics because they reveal depth of language knowledge.

Arithmetic Operators

a, b = 10, 3
 
print(a + b)   # 13  — addition
print(a - b)   # 7   — subtraction
print(a * b)   # 30  — multiplication
print(a / b)   # 3.3333... — true division (always returns float)
print(a // b)  # 3   — floor division (integer result)
print(a % b)   # 1   — modulo (remainder)
print(a ** b)  # 1000 — exponentiation
 
# Useful patterns
print(17 % 12)   # 5  — clock arithmetic
print(-7 % 3)    # 2  — Python modulo is always non-negative for positive divisor
print(2 ** 10)   # 1024
print(100 ** 0.5)  # 10.0 — square root via exponentiation

Comparison Operators

x, y = 5, 10
 
print(x == y)   # False — equal
print(x != y)   # True  — not equal
print(x < y)    # True  — less than
print(x > y)    # False — greater than
print(x <= y)   # True  — less than or equal
print(x >= y)   # False — greater than or equal
 
# Chained comparisons (Pythonic)
age = 25
print(18 <= age <= 65)   # True — between 18 and 65
print(1 < 2 < 3 < 4)     # True — all True

Logical Operators

# and, or, not
print(True and False)   # False
print(True or False)    # True
print(not True)         # False
 
# Short-circuit evaluation
def risky():
    raise ValueError("Should not be called")
 
print(False and risky())   # False — risky() never called
print(True or risky())     # True  — risky() never called
 
# Practical use
user = None
name = user and user["name"]   # safely avoid AttributeError
value = user or "default"       # fallback value

Assignment Operators

x = 10
x += 5    # x = x + 5  → 15
x -= 3    # x = x - 3  → 12
x *= 2    # x = x * 2  → 24
x //= 5   # x = x // 5 → 4
x **= 3   # x = x ** 3 → 64
x %= 10   # x = x % 10 → 4

Identity Operators: is and is not

is checks whether two variables point to the same object, not equal values.

a = [1, 2, 3]
b = [1, 2, 3]
c = a
 
print(a == b)    # True  — same values
print(a is b)    # False — different objects in memory
print(a is c)    # True  — same object
 
# None comparison — always use 'is'
result = None
if result is None:       # correct
    pass
if result == None:       # works but not idiomatic
    pass
 
# CPython interns small integers and short strings
x = 256
y = 256
print(x is y)   # True  — CPython caches -5 to 256
x = 257
y = 257
print(x is y)   # False — not cached (implementation detail)

Membership Operators: in and not in

fruits = ["apple", "banana", "cherry"]
 
print("apple" in fruits)      # True
print("mango" not in fruits)  # True
 
# String membership
print("py" in "python")       # True
print("xyz" not in "hello")   # True
 
# Dict membership (checks keys)
config = {"host": "localhost", "port": 5432}
print("host" in config)       # True
print("password" in config)   # False
 
# Set membership — O(1) lookup
tags = {"python", "web", "api"}
print("python" in tags)       # True — fastest membership test

Bitwise Operators

a = 0b1100  # 12
b = 0b1010  # 10
 
print(bin(a & b))   # 0b1000 (8)  — AND
print(bin(a | b))   # 0b1110 (14) — OR
print(bin(a ^ b))   # 0b0110 (6)  — XOR
print(bin(~a))      # -0b1101     — NOT (bitwise complement)
print(bin(a << 1))  # 0b11000 (24) — left shift (multiply by 2)
print(bin(a >> 1))  # 0b110 (6)    — right shift (divide by 2)
 
# Practical: check if number is even
def is_even(n: int) -> bool:
    return (n & 1) == 0
 
# Practical: swap without temp variable
x, y = 5, 10
x, y = x ^ y, x ^ y ^ (x ^ y)  # works but use tuple swap instead
x, y = y, x  # simpler and more Pythonic

Walrus Operator := (Python 3.8+)

The walrus operator assigns a value in an expression.

# Without walrus
data = get_data()
if data:
    process(data)
 
# With walrus (assign and check in one)
if data := get_data():
    process(data)
 
# In while loops
import re
 
text = "Hello 42 World 17"
pos = 0
while match := re.search(r"\d+", text[pos:]):
    print(match.group())
    pos += match.end()
 
# In comprehensions
values = [1, 2, 3, 4, 5, 6]
# Find and use transformed values
results = [y for x in values if (y := x ** 2) > 10]
# [16, 25, 36]

Operator Precedence (High to Low)

OperatorsDescription
**Exponentiation
+x, -x, ~xUnary
*, /, //, %Multiplication, division
+, -Addition, subtraction
&lt;&lt;, >>Bitwise shift
&Bitwise AND
^Bitwise XOR
|Bitwise OR
==, !=, &lt;, &gt;, &lt;=, &gt;=, is, inComparisons
notLogical NOT
andLogical AND
orLogical OR
:=Walrus

Common Mistakes

  • Using == to compare to None instead of is
  • Confusing and/or (logical) with &/| (bitwise) — different behavior
  • Expecting / to return an integer — use // for floor division
  • Misunderstanding modulo with negative numbers
  • Forgetting that not in is two words, not !in

Best Practices

  • Use is and is not for None, True, and False comparisons
  • Use parentheses to make complex expressions explicit rather than relying on precedence
  • Prefer // over int(a / b) for integer division
  • Use the walrus operator to simplify repetitive assignment patterns
  • Use in with sets for O(1) membership checks instead of lists

Key Takeaways

  • Python's / always returns a float; // returns the floor integer result
  • is compares object identity; == compares values — use is for None/True/False
  • and/or are logical operators with short-circuit evaluation; &/| are bitwise
  • in and not in test membership in sequences, sets, and dict keys
  • The walrus operator := assigns and returns a value in a single expression (Python 3.8+)
  • Chained comparisons like 1 &lt; x &lt; 10 work naturally in Python
  • When in doubt about precedence, use parentheses to be explicit

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro