Operators are the symbols Python uses to perform actions on data — adding numbers, comparing values, combining conditions, and more. If you have written even a single line of Python, you have already used them. This guide covers every operator category in Python with practical examples, a precedence reference, and the mistakes that trip up beginners most often.
Python groups its operators into seven categories. Each category serves a distinct purpose, and understanding when to reach for each one will make your code clearer and your logic tighter. We will work through them in the order you are most likely to encounter them as a beginner.
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric values. Python supports the standard four — addition, subtraction, multiplication, and division — plus three that newer programmers sometimes overlook: floor division, modulo, and exponentiation.
| Operator | Name | Example | Result |
|---|---|---|---|
+ |
Addition | 10 + 3 |
13 |
- |
Subtraction | 10 - 3 |
7 |
* |
Multiplication | 10 * 3 |
30 |
/ |
Division | 10 / 3 |
3.3333... |
// |
Floor division | 10 // 3 |
3 |
% |
Modulo | 10 % 3 |
1 |
** |
Exponentiation | 10 ** 3 |
1000 |
Division with / always returns a float in Python 3, even when the result divides evenly. Floor division with // truncates the decimal and returns an integer (or float if either operand is a float). The modulo operator % is one of the most useful operators for beginners — it tells you the remainder after division, and it is the standard way to check whether a number is even or odd.
# Division always returns a float in Python 3
print(10 / 2) # 5.0 — note the decimal
# Floor division truncates toward negative infinity
print(10 // 3) # 3
print(-10 // 3) # -4 — rounds DOWN, not toward zero
# Modulo: remainder after division
print(10 % 3) # 1
print(14 % 2) # 0 — 14 is even
# Exponentiation
print(2 ** 8) # 256
print(9 ** 0.5) # 3.0 — square root via fractional exponent
The + and * operators also work on strings and lists. "hello" + " world" concatenates two strings. "ha" * 3 produces "hahaha". This is called operator overloading — Python uses context to decide what an operator does.
Comparison Operators
Comparison operators compare two values and return a boolean — either True or False. They are the foundation of every conditional statement you will ever write.
| Operator | Meaning | Example | Result |
|---|---|---|---|
== |
Equal to | 5 == 5 |
True |
!= |
Not equal to | 5 != 3 |
True |
> |
Greater than | 5 > 3 |
True |
< |
Less than | 5 < 3 |
False |
>= |
Greater than or equal to | 5 >= 5 |
True |
<= |
Less than or equal to | 3 <= 5 |
True |
Python also supports chained comparisons, which read naturally and are more concise than writing two separate conditions joined by and.
age = 25
# Chained comparison — checks both conditions at once
if 18 <= age < 65:
print("Working age adult")
# This is equivalent to:
if age >= 18 and age < 65:
print("Working age adult")
# Strings compare lexicographically (alphabetical order)
print("apple" < "banana") # True
print("z" > "a") # True
Using = (assignment) instead of == (equality check) inside a condition is one of the classic beginner errors. In Python, writing if x = 5: raises a SyntaxError — unlike some other languages where it silently evaluates as an assignment. The error message is your friend here.
Logical Operators
Logical operators combine or modify boolean expressions. Python uses the English words and, or, and not rather than symbols, which makes conditions read more like sentences.
logged_in = True
has_permission = False
# and — both must be True
print(logged_in and has_permission) # False
# or — at least one must be True
print(logged_in or has_permission) # True
# not — inverts the boolean
print(not logged_in) # False
print(not has_permission) # True
A behavior that surprises many beginners: Python's logical operators use short-circuit evaluation. With and, if the left side is False, Python skips the right side entirely — the result cannot be True regardless. With or, if the left side is True, the right side is skipped. This matters when the right side has side effects like a function call.
Python's logical operators also return actual values rather than strictly True or False. The rule: and returns the first falsy value it finds, or the last value if all are truthy. or returns the first truthy value it finds, or the last value if all are falsy. This enables a concise pattern for supplying defaults.
# or returning actual values — classic default pattern
username = ""
display_name = username or "Anonymous"
print(display_name) # "Anonymous"
# and returning actual values
config = {"debug": True}
debug_mode = config and config.get("debug")
print(debug_mode) # True
In Python, the following values are considered falsy: False, None, 0, 0.0, "" (empty string), [] (empty list), {} (empty dict), and () (empty tuple). Everything else is truthy. Logical operators rely on this distinction.
Assignment Operators
The basic assignment operator = stores a value in a variable. Augmented assignment operators combine an arithmetic or bitwise operation with assignment in a single step, making code more concise and easier to read when updating a variable in place.
| Operator | Equivalent to | Example | Result (x starts at 10) |
|---|---|---|---|
= |
Assign | x = 10 |
x = 10 |
+= |
x = x + n |
x += 5 |
x = 15 |
-= |
x = x - n |
x -= 3 |
x = 7 |
*= |
x = x * n |
x *= 2 |
x = 20 |
/= |
x = x / n |
x /= 4 |
x = 2.5 |
//= |
x = x // n |
x //= 3 |
x = 3 |
%= |
x = x % n |
x %= 3 |
x = 1 |
**= |
x = x ** n |
x **= 2 |
x = 100 |
Python 3.8 introduced the walrus operator :=, which assigns a value and returns it in the same expression. It is useful in while loops and list comprehensions where you want to capture an intermediate result without an extra line of code.
# Without walrus operator
data = input("Enter something: ")
while len(data) > 0:
print(f"You entered: {data}")
data = input("Enter something: ")
# With walrus operator — cleaner loop
while (data := input("Enter something: ")):
print(f"You entered: {data}")
Bitwise Operators
Bitwise operators work directly on the binary representation of integers. They are less common in everyday scripting but appear frequently in systems programming, cryptography, networking, and any situation where you need to manipulate individual bits efficiently.
| Operator | Name | Example (a=5, b=3) | Result |
|---|---|---|---|
& |
AND | 5 & 3 |
1 |
| |
OR | 5 | 3 |
7 |
^ |
XOR | 5 ^ 3 |
6 |
~ |
NOT | ~5 |
-6 |
<< |
Left shift | 5 << 1 |
10 |
>> |
Right shift | 5 >> 1 |
2 |
# 5 in binary: 0101
# 3 in binary: 0011
print(5 & 3) # 0001 = 1 (both bits must be 1)
print(5 | 3) # 0111 = 7 (either bit can be 1)
print(5 ^ 3) # 0110 = 6 (bits differ)
# Left shift multiplies by powers of 2
print(5 << 1) # 10 (5 * 2)
print(5 << 2) # 20 (5 * 4)
# Right shift divides by powers of 2 (integer result)
print(20 >> 1) # 10 (20 / 2)
print(20 >> 2) # 5 (20 / 4)
# Practical use: check if a number is odd using bitwise AND
num = 7
print(num & 1) # 1 = odd (least significant bit is 1)
num = 8
print(num & 1) # 0 = even
As of Python 3.9, the | operator also merges two dictionaries. dict_a | dict_b returns a new dictionary combining both, with values from dict_b winning any key conflicts. This is separate from the bitwise OR behavior on integers — Python uses the operand types to decide which operation to perform.
Identity and Membership Operators
These two categories are often grouped together because they both read like plain English and beginners sometimes confuse them with comparison operators.
Identity Operators: is and is not
Identity operators check whether two variables point to the same object in memory, not just whether their values are equal. This is a meaningful distinction in Python because two variables can hold equal values while referencing different objects.
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 — c points to the same object as a
# The correct way to check for None
result = None
print(result is None) # True — preferred style
print(result == None) # True — works but not recommended
print(result is not None) # False
Do not use is to compare integers or strings in general. Python caches small integers (typically -5 through 256) and some short strings, so is can appear to work — but this is an implementation detail, not a guarantee. For value equality, always use ==. Reserve is for checking against None, True, and False.
Membership Operators: in and not in
Membership operators check whether a value exists inside a sequence — a string, list, tuple, set, or dictionary.
fruits = ["apple", "banana", "cherry"]
print("banana" in fruits) # True
print("mango" not in fruits) # True
# Works on strings too
message = "Hello, world!"
print("world" in message) # True
# Checking dictionary keys
user = {"name": "Kandi", "role": "admin"}
print("role" in user) # True — checks keys
print("admin" in user) # False — "admin" is a value, not a key
print("admin" in user.values()) # True
When checking membership against a large collection, prefer a set over a list. Checking x in some_set runs in constant time O(1) regardless of collection size. Checking x in some_list scans every element and runs in O(n) time. For small collections it does not matter, but at scale the difference is significant.
Operator Precedence
When an expression contains multiple operators, Python evaluates them in a defined order — just like the mathematical order of operations you learned in school, extended to cover Python's full operator set. Higher rows in the table below are evaluated first.
| Priority | Operators | Description |
|---|---|---|
| 1 (highest) | () |
Parentheses |
| 2 | ** |
Exponentiation |
| 3 | +x, -x, ~x |
Unary plus, minus, bitwise NOT |
| 4 | *, /, //, % |
Multiplication, division, floor division, modulo |
| 5 | +, - |
Addition, subtraction |
| 6 | <<, >> |
Bitwise shifts |
| 7 | & |
Bitwise AND |
| 8 | ^ |
Bitwise XOR |
| 9 | | |
Bitwise OR |
| 10 | ==, !=, >, <, >=, <=, is, is not, in, not in |
Comparisons, identity, membership |
| 11 | not |
Logical NOT |
| 12 | and |
Logical AND |
| 13 (lowest) | or |
Logical OR |
# Without parentheses — precedence determines the result
print(2 + 3 * 4) # 14 — multiplication before addition
print(2 ** 3 ** 2) # 512 — exponentiation is right-associative: 3**2=9, then 2**9
# With parentheses — you control the order
print((2 + 3) * 4) # 20
print((2 ** 3) ** 2) # 64
# Mixing comparison and logical operators
x = 5
print(x > 3 and x < 10) # True — comparisons evaluate before 'and'
print(not x > 3 or x == 5) # True — 'not' before 'or', comparisons first
"Programs must be written for people to read, and only incidentally for machines to execute." — Harold Abelson
When precedence rules make an expression difficult to read, add parentheses anyway — even when they are not strictly required. Parentheses make your intent explicit and save the next reader (including future you) from mentally simulating the evaluation order.
Key Takeaways
- Division always produces a float: Use
//when you need an integer result. Use%to extract the remainder. - == checks value equality; is checks object identity: Use
isonly withNone,True, andFalse. Use==for everything else. - Logical operators return values, not just booleans: Short-circuit evaluation and truthy/falsy values enable concise default patterns like
name = user_input or "Anonymous". - Augmented assignment keeps code readable:
x += 1is cleaner thanx = x + 1and conveys that you are updating an existing variable rather than creating a new one. - When in doubt, use parentheses: Precedence rules are well-defined, but explicit grouping makes code easier to read and reduces the chance of subtle bugs when expressions grow complex.
Operators are one of the smallest building blocks in Python, but they sit inside nearly every expression you write. Getting comfortable with how each category behaves — and where the surprising edges are — gives you a solid foundation for everything that comes next.