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]) # TrueSequence 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) # 1In-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 8Functional 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')) # bobgetitem 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') # 1Performance 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% fasterReal-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
| Operator | Function | Example |
|---|---|---|
+ | 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.attr | attrgetter('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: