The operator module provides function equivalents of Python operators. Faster and cleaner than lambdas for common operations.

itemgetter: Access by Index or Key

from operator import itemgetter
 
# Get item by index
get_first = itemgetter(0)
print(get_first([1, 2, 3]))  # 1
 
# Get multiple items
get_ends = itemgetter(0, -1)
print(get_ends([1, 2, 3, 4, 5]))  # (1, 5)
 
# Get dict value
get_name = itemgetter('name')
print(get_name({'name': 'Alice', 'age': 30}))  # Alice

Sorting with itemgetter

from operator import itemgetter
 
users = [
    {'name': 'Alice', 'age': 30},
    {'name': 'Bob', 'age': 25},
    {'name': 'Carol', 'age': 35},
]
 
# Sort by key
sorted_by_age = sorted(users, key=itemgetter('age'))
 
# Sort by multiple keys
data = [('Alice', 'B'), ('Bob', 'A'), ('Alice', 'A')]
sorted_data = sorted(data, key=itemgetter(0, 1))
# [('Alice', 'A'), ('Alice', 'B'), ('Bob', 'A')]

attrgetter: Access Attributes

from operator import attrgetter
from dataclasses import dataclass
 
@dataclass
class User:
    name: str
    age: int
 
users = [User('Alice', 30), User('Bob', 25), User('Carol', 35)]
 
# Sort by attribute
sorted_users = sorted(users, key=attrgetter('age'))
 
# Get attribute value
get_name = attrgetter('name')
names = [get_name(u) for u in users]  # ['Alice', 'Bob', 'Carol']
 
# Multiple attributes
get_info = attrgetter('name', 'age')
print(get_info(users[0]))  # ('Alice', 30)

Nested Attributes

from operator import attrgetter
 
class Address:
    def __init__(self, city):
        self.city = city
 
class Person:
    def __init__(self, name, address):
        self.name = name
        self.address = address
 
person = Person('Alice', Address('NYC'))
 
# Access nested attribute
get_city = attrgetter('address.city')
print(get_city(person))  # NYC

methodcaller: Call Methods

from operator import methodcaller
 
# Call method with no args
upper = methodcaller('upper')
print(upper('hello'))  # HELLO
 
# Call method with args
split_comma = methodcaller('split', ',')
print(split_comma('a,b,c'))  # ['a', 'b', 'c']
 
# Call method with kwargs
format_num = methodcaller('format', '.2f')
print(format_num(3.14159))  # Error - format() doesn't work this way
 
# Practical use
strip_lower = methodcaller('strip')
words = ['  hello ', ' world  ']
cleaned = list(map(strip_lower, words))  # ['hello', 'world']

Operator Functions

Replace operators with functions:

from operator import add, sub, mul, truediv, mod, pow
from operator import eq, ne, lt, le, gt, ge
from operator import and_, or_, not_
from operator import neg, pos, abs as abs_
 
# Arithmetic
add(2, 3)       # 5
mul(4, 5)       # 20
truediv(10, 3)  # 3.333...
pow(2, 8)       # 256
 
# Comparison
lt(1, 2)  # True
eq(5, 5)  # True
 
# Boolean
and_(True, False)  # False
not_(True)         # False
 
# With reduce
from functools import reduce
reduce(add, [1, 2, 3, 4, 5])  # 15
reduce(mul, [1, 2, 3, 4, 5])  # 120

Container Operations

from operator import contains, countOf, indexOf
from operator import getitem, setitem, delitem
 
# contains
contains([1, 2, 3], 2)  # True (same as 2 in [1, 2, 3])
 
# countOf
countOf([1, 2, 2, 3, 2], 2)  # 3
 
# indexOf
indexOf([1, 2, 3], 2)  # 1
 
# Item access
data = [1, 2, 3]
getitem(data, 1)      # 2
setitem(data, 1, 99)  # data is now [1, 99, 3]

Why operator Over lambdas?

from operator import itemgetter, attrgetter
 
# Lambda: slower, less readable
sorted(users, key=lambda x: x['age'])
sorted(users, key=lambda x: x.name)
 
# operator: faster, cleaner
sorted(users, key=itemgetter('age'))
sorted(users, key=attrgetter('name'))

Performance: itemgetter and attrgetter are implemented in C, making them faster than equivalent lambdas.

Practical Examples

Finding Max by Attribute

from operator import attrgetter
 
@dataclass
class Product:
    name: str
    price: float
 
products = [
    Product('Apple', 1.50),
    Product('Banana', 0.75),
    Product('Cherry', 3.00),
]
 
most_expensive = max(products, key=attrgetter('price'))
# Product(name='Cherry', price=3.0)

Grouping by Key

from operator import itemgetter
from itertools import groupby
 
data = [
    ('fruit', 'apple'),
    ('fruit', 'banana'),
    ('veggie', 'carrot'),
    ('fruit', 'cherry'),
    ('veggie', 'daikon'),
]
 
# Sort then group
data.sort(key=itemgetter(0))
for category, items in groupby(data, key=itemgetter(0)):
    print(f"{category}: {list(items)}")

Extracting Columns

from operator import itemgetter
 
rows = [
    ('Alice', 30, 'NYC'),
    ('Bob', 25, 'LA'),
    ('Carol', 35, 'Chicago'),
]
 
# Extract name and city columns
extract = itemgetter(0, 2)
extracted = [extract(row) for row in rows]
# [('Alice', 'NYC'), ('Bob', 'LA'), ('Carol', 'Chicago')]

Chaining Method Calls

from operator import methodcaller
 
# Process strings
strip = methodcaller('strip')
lower = methodcaller('lower')
 
def clean(s):
    return lower(strip(s))
 
data = ['  Hello  ', ' WORLD ', '  Python  ']
cleaned = [clean(s) for s in data]
# ['hello', 'world', 'python']

Quick Reference

from operator import (
    # Getters
    itemgetter,    # obj[key]
    attrgetter,    # obj.attr
    methodcaller,  # obj.method(*args)
    
    # Arithmetic
    add, sub, mul, truediv, floordiv, mod, pow,
    neg, pos, abs,
    
    # Comparison
    eq, ne, lt, le, gt, ge,
    
    # Logical
    and_, or_, not_,
    
    # Container
    contains, countOf, indexOf,
    getitem, setitem, delitem,
)
FunctionEquivalent
itemgetter(k)lambda x: x[k]
attrgetter(a)lambda x: x.a
methodcaller(m)lambda x: x.m()
add(a, b)a + b
contains(a, b)b in a

Use operator when you need a function for what would normally be an operator or simple attribute access.

React to this post: