Python Operators

Python operators are the building blocks of every expression you write. They combine variables and values to produce new values, control program flow, and make decisions. If you have written any Python code at all, you have used operators. This guide covers every operator Python offers, with working examples you can run yourself.

Each section explains what an operator does, shows it in context, and flags common mistakes. Work through it end to end or jump to the operator type you need. Everything here works in Python 3.13 and later.

TLDR

  • Arithmetic operators: + – * / // % ** for math
  • Comparison operators: == != < > <= >= return True or False
  • Logical operators: and, or, not combine boolean values
  • Bitwise operators: & | ^ ~ << >> work on individual bits
  • Use parentheses to control evaluation order when operator precedence is unclear

Arithmetic Operators

Arithmetic operators perform mathematical calculations. Python supports seven basic arithmetic operators. The division operator / always returns a float. Floor division // returns an integer by discarding the fractional part. The modulus operator % returns the remainder after division. The ** operator raises a number to a power.

x = 15
y = 4

print(x + y)   # 19
print(x - y)   # 11
print(x * y)   # 60
print(x / y)   # 3.75  (true division always returns float)
print(x // y)  # 3     (floor division)
print(x % y)   # 3     (modulus: remainder after division)
print(x ** y)  # 50625 (15 to the power of 4)

Division Behavior

Python has two division operators. True division / returns a floating point result. Floor division // discards the fractional part and returns an integer when both operands are integers. This distinction matters when working with financial calculations or anything requiring precise decimal arithmetic.

print(7 / 2)   # 3.5
print(7 // 2)  # 3
print(-7 / 2)  # -3.5
print(-7 // 2) # -4  (floors toward negative infinity)

Modulus With Negative Numbers

The modulus operator % can produce unexpected negative results when the divisor is negative. The sign of the result follows the sign of the divisor, not the dividend. Python follows the IEEE 754 standard for this behavior.

print(7 % 3)    # 1
print(7 % -3)   # -2
print(-7 % 3)    # 2
print(-7 % -3)   # -1

String Operators

Two operators work on strings. The + operator concatenates two strings. The * operator repeats a string. There is no subtraction operator for strings. You cannot add a string and a number directly; you must convert the number to a string first.

print("Py" + "thon")      # Python
print("Ha" * 3)           # HaHaHa
print("-" * 40)           # ----------------------------------------

# Error: cannot concatenate string and int
# print("Age: " + 25)       # TypeError
print("Age: " + str(25))   # Age: 25

Comparison Operators

Comparison operators evaluate to True or False. They are used in conditional statements, loops, and anywhere you need to compare values. Python allows chaining comparisons, so you can write 0 < x < 10 to check if x falls within a range. String comparisons use lexicographic ordering based on Unicode code points.

x = 10
y = 20

print(x == y)   # False
print(x != y)    # True
print(x < y)     # True
print(x > y)     # False
print(x <= y)    # True
print(x >= y)    # False

Chained Comparisons

Python lets you chain comparison operators naturally. The expression 0 < x < 10 is evaluated as (0 < x) and (x < 10), but Python evaluates it more efficiently without creating an intermediate boolean. This is cleaner and slightly faster than writing it out explicitly.

x = 5
print(0 < x < 10)       # True
print(0 < x < 3)        # False
print(1 < x < 4 < 10)   # True  (chained: 1<x and x<4 and 4<10)

Logical Operators

Logical operators combine boolean values. and returns True only when both operands are True. or returns True when at least one operand is True. not inverts the boolean value. Python uses short-circuit evaluation, which means it stops evaluating as soon as the result is determined.

b1 = True
b2 = False

print(b1 and b2)   # False
print(b1 or b2)     # True
print(not b1)       # False

Short-Circuit Evaluation

Short-circuit evaluation skips the second operand when the result can be determined from the first. For and, if the first operand is False, the second is never evaluated. For or, if the first is True, the second is skipped. This matters when the second expression would cause an error or be expensive to compute.

x = 0

# x is falsy, so and stops here and returns 0 (not evaluates y)
result = x and 10 / x
print(result)  # 0

# x is falsy, so or evaluates the second expression
result = x or 42
print(result)  # 42

Bitwise Operators

Bitwise operators manipulate individual bits of integer values. They are used in low-level programming, flag manipulation, and optimization. Understanding binary representation helps when working with bitwise operators. Python displays integers in decimal by default but stores them efficiently in binary internally.

x = 10   # binary: 1010
y = 4    # binary: 0100

print(x & y)    # 0    (1010 AND 0100 = 0000)
print(x | y)    # 14   (1010 OR  0100 = 1110)
print(x ^ y)    # 14   (1010 XOR 0100 = 1110)
print(~x)       # -11  (bitwise NOT: -x - 1)
print(x << 2)   # 40   (1010 << 2 = 101000 = 40)
print(x >> 2)   # 2    (1010 >> 2 = 10 = 2)

Shift Operators

Left shift << appends zeros to the binary representation, effectively multiplying by 2 for each shift position. Right shift >> removes bits from the right. For positive integers, right shift is floor division by 2. For negative integers, the behavior is implementation-defined in Python but typically preserves the sign.

x = 8
print(x << 1)    # 16  (multiply by 2)
print(x << 2)    # 32  (multiply by 4)
print(x >> 1)    # 4   (floor divide by 2)

x = -8
print(x >> 2)    # -2

Assignment Operators

Assignment operators store values in variables. The basic = operator assigns the right-hand value to the left-hand variable. Compound assignment operators like += perform an operation and assignment in one step. They are equivalent to their expanded form but often slightly faster and more readable.

a = 10
a += 5    # a = 15
a -= 3    # a = 12
a *= 2    # a = 24
a /= 4    # a = 6.0  (division always produces float)
a //= 2   # a = 3.0
a %= 2    # a = 1.0
a **= 2   # a = 1.0

Identity Operators

Identity operators check whether two variables refer to the same object in memory, not whether they have the same value. Use is to test for None, which is a singleton. For everything else, equality is tested with ==, not is. Comparing with is works for small integers and interned strings but is not reliable for general equality checks.

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a is b)       # False  (different objects)
print(a is c)       # True   (same object)
print(a == b)       # True   (same values)

# Common pattern
result = None
if result is None:
    print("No result yet")

Membership Operators

Membership operators test whether a value is contained in a sequence. in returns True if the value is found. not in returns True if the value is not found. These operators work with any iterable: lists, tuples, strings, dictionaries, sets, and more. For dictionaries, in checks keys, not values.

my_list = [1, 2, 3, 4, 5]
print(3 in my_list)       # True
print(6 in my_list)       # False

my_dict = {"a": 1, "b": 2}
print("a" in my_dict)      # True
print(1 in my_dict)       # False (1 is a value, not a key)

my_str = "Hello World"
print("World" in my_str)   # True

Operator Precedence

Operator precedence determines which operator is evaluated first when an expression contains multiple operators. Operators with higher precedence bind more tightly. When operators have the same precedence, they are evaluated left to right except for exponentiation, which evaluates right to left. Using parentheses makes intent clear and avoids bugs.

# Without parentheses:
# ** binds tightest, then *///%, then +-, then &lt;&lt;&gt;&gt;, then &amp;, then ^, then |

result = 2 + 3 * 4      # 14, not 20 (multiplication first)
result = (2 + 3) * 4    # 20 (parentheses override)

# Exponentiation is right-associative
print(2 ** 3 ** 2)      # 512, not 64 (rightmost first: 3**2=9, then 2**9=512)

# Boolean operators have lower precedence than arithmetic
print(1 + 2 and 3 + 4)  # 7 (1+2=3 is truthy, so 3+4=7)

Ternary Conditional Operator

The ternary operator is a shorthand for simple if-else statements. It evaluates a condition and returns one of two values based on whether the condition is True or False. The syntax is value_if_true if condition else value_if_false. Use it for simple conditional assignments; prefer full if-else blocks for complex logic.

age = 20
status = "adult" if age >= 18 else "minor"
print(status)  # adult

# Can chain but readability suffers
score = 85
grade = "A" if score >= 90 else "B" if score >= 80 else "C"
print(grade)  # B

Operator Overloading With Special Methods

Python allows you to define how operators behave for custom objects by implementing special methods. These dunder methods (double underscore) are called automatically when the corresponding operator is used. Defining __eq__ makes == work for your class. Defining __lt__ enables sorting of your objects. Python calls these automatically; you never call them directly.

class Vector:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vector({self.x}, {self.y})"

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __lt__(self, other):
        return (self.x ** 2 + self.y ** 2) < (other.x ** 2 + other.y ** 2)

v1 = Vector(3, 4)
v2 = Vector(3, 4)
v3 = Vector(5, 12)

print(v1 == v2)  # True (__eq__ defined)
print(v1 < v3)   # True (__lt__ defined)

Common Special Methods

Most operators have corresponding special methods. Implementing only the ones you need keeps your class simple. The most commonly overloaded operators are comparison operators, arithmetic operators, and container-style access. Always implement __repr__ for debugging; Python calls it when you print an object.

# Arithmetic
__add__(self, other)      # a + b
__sub__(self, other)       # a - b
__mul__(self, other)      # a * b
__truediv__(self, other)  # a / b
__floordiv__(self, other) # a // b
__mod__(self, other)      # a % b
__pow__(self, other)      # a ** b

# In-place (optional, Python falls back to non-in-place if not defined)
__iadd__(self, other)     # a += b

# Comparison (can also use functools.total_ordering as a shortcut)
__eq__(self, other)       # a == b
__lt__(self, other)       # a < b
__le__(self, other)       # a <= b
__gt__(self, other)       # a > b
__ge__(self, other)       # a >= b

The Operator Module

The operator module provides functional equivalents of Python operators. These are useful when you need to pass an operator as a argument to a function, such as sorted, map, or reduce. Using operator.add is equivalent to lambda a, b: a + b but slightly faster and more readable. The module also provides itemgetter and attrgetter for accessing object attributes and dictionary values.

import operator

# Equivalent to lambda a, b: a + b
add = operator.add
print(add(10, 20))           # 30

# Functional versions of augmented assignment
operator.iadd
operator.isub
operator.imul

# Truthiness checks
print(operator.truth(True))     # True
print(operator.truth(0))        # False

# Item access
get_item = operator.itemgetter(0)
print(get_item([10, 20, 30]))   # 10

#.attrgetter
from collections import namedtuple
Person = namedtuple("Person", ["name", "age"])
people = [Person("Alice", 30), Person("Bob", 25)]
people.sort(key=operator.attrgetter("age"))
print([p.name for p in people])  # ["Bob", "Alice"]

FAQ

What is the difference between == and is?

== tests value equality, is tests identity (whether two variables point to the same object in memory). Use == for comparing values, is for comparing with None or checking object identity. Two objects with equal values may still be different objects.

Why does -7 // 2 return -4?

Python floor division floors toward negative infinity. -3.5 floors to -4. This differs from truncation, which would give -3. Python follows IEEE 754 semantics for floor division with negative numbers.

What is the fastest way to concatenate many strings?

For a small number of strings, + works fine. For many strings in a loop, use a list and join. For building strings from known parts, f-strings are the most readable and performant option.

Can I define operators for my own classes?

Yes. Implement the corresponding special methods (__add__, __eq__, __lt__, etc.). Python calls these automatically when you use the operator on your objects. The functools.total_ordering decorator helps by generating missing comparison methods from a minimal set.

What does the walrus operator := do?

The walrus operator := assigns and returns the value in a single expression. It is useful in loops and comprehensions where you want to compute a value once and reuse it. Example: if (n := len(data)) > 10: processes the data after computing its length once.

Pankaj Kumar
Pankaj Kumar

I have been working on Python programming for more than 12 years. At AskPython, I share my learning on Python with other fellow developers.

Articles: 244