The operator module provides function equivalents of Python's operators. Cleaner than lambdas, faster in some cases, and essential for functional programming patterns.

Why Use operator?

from operator import add, mul, itemgetter
 
# Instead of lambda
sorted(items, key=lambda x: x[1])
# Use operator
sorted(items, key=itemgetter(1))
 
# Instead of lambda in reduce
from functools import reduce
reduce(lambda a, b: a + b, numbers)
# Use operator
reduce(add, numbers)

Arithmetic Operators

from operator import add, sub, mul, truediv, floordiv, mod, pow, neg
 
add(5, 3)       # 8      (5 + 3)
sub(5, 3)       # 2      (5 - 3)
mul(5, 3)       # 15     (5 * 3)
truediv(5, 3)   # 1.666  (5 / 3)
floordiv(5, 3)  # 1      (5 // 3)
mod(5, 3)       # 2      (5 % 3)
pow(5, 3)       # 125    (5 ** 3)
neg(5)          # -5     (-5)

Comparison Operators

from operator import eq, ne, lt, le, gt, ge
 
eq(5, 5)   # True   (5 == 5)
ne(5, 3)   # True   (5 != 3)
lt(3, 5)   # True   (3 < 5)
le(3, 3)   # True   (3 <= 3)
gt(5, 3)   # True   (5 > 3)
ge(5, 5)   # True   (5 >= 5)

itemgetter for Sorting

from operator import itemgetter
 
# Sort by index
data = [('alice', 25), ('bob', 30), ('carol', 20)]
 
# Sort by second element (age)
sorted(data, key=itemgetter(1))
# [('carol', 20), ('alice', 25), ('bob', 30)]
 
# Sort by multiple keys
data = [('alice', 25, 'A'), ('bob', 25, 'B'), ('carol', 20, 'C')]
sorted(data, key=itemgetter(1, 0))  # By age, then name
 
# Works with dicts too
users = [{'name': 'alice', 'age': 25}, {'name': 'bob', 'age': 30}]
sorted(users, key=itemgetter('age'))

attrgetter for Object Attributes

from operator import attrgetter
 
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
users = [User('alice', 25), User('bob', 30), User('carol', 20)]
 
# Sort by attribute
sorted(users, key=attrgetter('age'))
 
# Multiple attributes
sorted(users, key=attrgetter('age', 'name'))
 
# Nested attributes
class Profile:
    def __init__(self, user):
        self.user = user
 
profiles = [Profile(u) for u in users]
sorted(profiles, key=attrgetter('user.age'))

methodcaller

from operator import methodcaller
 
# Call method on each object
strings = ['hello', 'WORLD', 'Python']
 
# Instead of: [s.upper() for s in strings]
list(map(methodcaller('upper'), strings))
# ['HELLO', 'WORLD', 'PYTHON']
 
# With arguments
methodcaller('replace', 'o', '0')('hello')
# 'hell0'
 
# Sorting with method
sorted(strings, key=methodcaller('lower'))
# ['hello', 'Python', 'WORLD']

Bitwise Operators

from operator import and_, or_, xor, invert, lshift, rshift
 
and_(0b1100, 0b1010)  # 0b1000 (8)
or_(0b1100, 0b1010)   # 0b1110 (14)
xor(0b1100, 0b1010)   # 0b0110 (6)
invert(0b0000)        # -1 (~0)
lshift(1, 4)          # 16 (1 << 4)
rshift(16, 2)         # 4 (16 >> 2)

Boolean Operators

from operator import not_, truth
 
not_(True)   # False
not_(0)      # True
truth(1)     # True
truth([])    # False
truth([1])   # True

Sequence Operators

from operator import concat, contains, countOf, indexOf
 
concat([1, 2], [3, 4])     # [1, 2, 3, 4]
concat('hello', ' world')  # 'hello world'
 
contains([1, 2, 3], 2)     # True
countOf([1, 2, 2, 3], 2)   # 2
indexOf([1, 2, 3], 2)      # 1

In-Place Operators

from operator import iadd, imul, isub
 
# These modify in place (for mutable objects)
lst = [1, 2]
iadd(lst, [3, 4])  # lst is now [1, 2, 3, 4]
 
# For immutable, returns new value
x = 5
x = iadd(x, 3)  # x is now 8

Functional reduce Patterns

from functools import reduce
from operator import add, mul, or_, and_
 
numbers = [1, 2, 3, 4, 5]
 
# Sum (though sum() is better)
reduce(add, numbers)  # 15
 
# Product
reduce(mul, numbers)  # 120
 
# Combine sets
sets = [{1, 2}, {2, 3}, {3, 4}]
reduce(or_, sets)   # {1, 2, 3, 4} (union)
reduce(and_, sets)  # set() (intersection, empty here)

max/min with operator

from operator import itemgetter, attrgetter
 
# Find max by specific key
data = [('alice', 25), ('bob', 30), ('carol', 20)]
max(data, key=itemgetter(1))  # ('bob', 30)
min(data, key=itemgetter(1))  # ('carol', 20)
 
# With objects
users = [User('alice', 25), User('bob', 30)]
max(users, key=attrgetter('age'))  # bob

getitem and setitem

from operator import getitem, setitem, delitem
 
data = [10, 20, 30, 40]
 
getitem(data, 1)        # 20
setitem(data, 1, 25)    # data[1] = 25
delitem(data, 1)        # del data[1]
 
# With dicts
d = {'a': 1, 'b': 2}
getitem(d, 'a')         # 1

Performance Comparison

from operator import add, itemgetter
import timeit
 
data = list(range(1000))
 
# operator is often faster than lambda
lambda_time = timeit.timeit(
    lambda: sorted([(i, i*2) for i in data], key=lambda x: x[1]),
    number=1000
)
 
operator_time = timeit.timeit(
    lambda: sorted([(i, i*2) for i in data], key=itemgetter(1)),
    number=1000
)
 
print(f"Lambda: {lambda_time:.3f}s")
print(f"Operator: {operator_time:.3f}s")
# Operator is typically 10-30% faster

Real-World Patterns

Grouping by Attribute

from operator import attrgetter
from itertools import groupby
 
users = [
    User('alice', 25),
    User('bob', 25),
    User('carol', 30),
]
 
# Group by age
users.sort(key=attrgetter('age'))
for age, group in groupby(users, key=attrgetter('age')):
    print(f"Age {age}: {[u.name for u in group]}")

Dictionary Sorting

from operator import itemgetter
 
scores = {'alice': 95, 'bob': 87, 'carol': 92}
 
# Sort by value
sorted(scores.items(), key=itemgetter(1), reverse=True)
# [('alice', 95), ('carol', 92), ('bob', 87)]

Data Pipeline

from operator import itemgetter, methodcaller
from functools import reduce
 
# Process list of dicts
data = [
    {'name': 'Alice', 'score': 95},
    {'name': 'Bob', 'score': 87},
]
 
# Extract, transform, reduce
names = list(map(itemgetter('name'), data))
upper_names = list(map(methodcaller('upper'), names))

Quick Reference

OperatorFunctionExample
+add(a, b)add(2, 3) → 5
-sub(a, b)sub(5, 3) → 2
*mul(a, b)mul(2, 3) → 6
==eq(a, b)eq(2, 2) → True
<lt(a, b)lt(2, 3) → True
[]getitem(a, b)getitem([1,2], 0) → 1
obj.attrattrgetter('attr')Sort by attribute
d['key']itemgetter('key')Sort by key

The operator module makes functional programming cleaner and often faster. Use it instead of lambdas for standard operations.

React to this post: