Utilities
Operator Module
Lambda functions for simple operations like getting an attribute or adding numbers add visual noise and reduce readability. The operator module provides efficient, named functions for built-in operators, making sorting keys and functional operations clearer and faster.
Comparison Operations
Function versions of comparison operators:
itemgetter.py
"""operator.itemgetter examples"""
import operator
# Basic itemgetter
print("Basic itemgetter:")
# Get single item
get_first = operator.itemgetter(0)
numbers =
print(f"get_first({numbers}): {get_first(numbers)}")
# Get by key
data = {'name': 'Alice', 'age': 30}
get_name = operator.itemgetter('name')
print(f"get_name({data}): {get_name(data)}")
# Multiple items
print("\nMultiple items:")
# Get multiple indices
get_items = operator.itemgetter(0, 2, 4)
letters = ['a', 'b', 'c', 'd', 'e']
result = get_items(letters)
print(f"get_items({letters}): {result}")
# Multiple keys
get_info = operator.itemgetter('name', 'age')
person = {'name': 'Bob', 'age': 25, 'city': 'NYC'}
print(f"get_info: {get_info(person)}")
# Sorting lists
print("\nSorting lists:")
students = [
{'name': 'Charlie', 'grade': 85},
{'name': 'Alice', 'grade': 92},
{'name': 'Bob', 'grade': 78}
]
# Sort by grade
sorted_by_grade = sorted(students, key=operator.itemgetter('grade'))
print("Sorted by grade:")
for s in sorted_by_grade:
print(f" {s}")
# Sort by name
sorted_by_name = sorted(students, key=operator.itemgetter('name'))
print("\nSorted by name:")
for s in sorted_by_name:
print(f" {s}")
# Nested sorting
print("\nNested sorting:")
data = [
{'name': 'Alice', 'scores': [85, 90]},
{'name': 'Bob', 'scores': [92, 88]},
{'name': 'Charlie', 'scores': [78, 95]}
]
# Sort by first score
sorted_data = sorted(data,
key=lambda x: operator.itemgetter(0)(x['scores']))
print("Sorted by first score:")
for d in sorted_data:
print(f" {d}")
# With tuples
print("\nWith tuples:")
records = [
('Alice', 30, 'NYC'),
('Bob', 25, 'LA'),
('Charlie', 35, 'Chicago')
]
# Sort by age (index 1)
sorted_by_age = sorted(records, key=operator.itemgetter(1))
print("Sorted by age:")
for r in sorted_by_age:
print(f" {r}")
# Sort by multiple fields (city, then age)
sorted_multi = sorted(records, key=operator.itemgetter(2, 1))
print("\nSorted by city then age:")
for r in sorted_multi:
print(f" {r}")
# Map and filter
print("\nMap and filter:")
users = [
{'id': 1, 'name': 'Alice', 'active': True},
{'id': 2, 'name': 'Bob', 'active': False},
{'id': 3, 'name': 'Charlie', 'active': True}
]
# Extract all names
names = list(map(operator.itemgetter('name'), users))
print(f"Names: {names}")
# Extract ids of active users
active_ids = [
operator.itemgetter('id')(user)
for user in users
if user['active']
]
print(f"Active IDs: {active_ids}")
# Min/max
print("\nMin/max:")
products = [
{'name': 'Widget', 'price': 29.99},
{'name': 'Gadget', 'price': 49.99},
{'name': 'Tool', 'price': 19.99}
]
cheapest = min(products, key=operator.itemgetter('price'))
print(f"Cheapest: {cheapest}")
most_expensive = max(products, key=operator.itemgetter('price'))
print(f"Most expensive: {most_expensive}")
# Grouping
print("\nGrouping:")
from itertools import groupby
transactions = [
{'category': 'food', 'amount': 50},
{'category': 'transport', 'amount': 20},
{'category': 'food', 'amount': 30},
{'category': 'transport', 'amount': 15}
]
# Must sort first for groupby
transactions.sort(key=operator.itemgetter('category'))
for category, items in groupby(transactions,
key=operator.itemgetter('category')):
total = sum(operator.itemgetter('amount')(item) for item in items)
print(f"{category}: ${total}")
"""operator.itemgetter examples"""
import operator
# Basic itemgetter
print("Basic itemgetter:")
# Get single item
get_first = operator.itemgetter(0)
numbers =
print(f"get_first({numbers}): {get_first(numbers)}")
# Get by key
data = {'name': 'Alice', 'age': 30}
get_name = operator.itemgetter('name')
print(f"get_name({data}): {get_name(data)}")
# Multiple items
print("\nMultiple items:")
# Get multiple indices
get_items = operator.itemgetter(0, 2, 4)
letters = ['a', 'b', 'c', 'd', 'e']
result = get_items(letters)
print(f"get_items({letters}): {result}")
# Multiple keys
get_info = operator.itemgetter('name', 'age')
person = {'name': 'Bob', 'age': 25, 'city': 'NYC'}
print(f"get_info: {get_info(person)}")
# Sorting lists
print("\nSorting lists:")
students = [
{'name': 'Charlie', 'grade': 85},
{'name': 'Alice', 'grade': 92},
{'name': 'Bob', 'grade': 78}
]
# Sort by grade
sorted_by_grade = sorted(students, key=operator.itemgetter('grade'))
print("Sorted by grade:")
for s in sorted_by_grade:
print(f" {s}")
# Sort by name
sorted_by_name = sorted(students, key=operator.itemgetter('name'))
print("\nSorted by name:")
for s in sorted_by_name:
print(f" {s}")
# Nested sorting
print("\nNested sorting:")
data = [
{'name': 'Alice', 'scores': [85, 90]},
{'name': 'Bob', 'scores': [92, 88]},
{'name': 'Charlie', 'scores': [78, 95]}
]
# Sort by first score
sorted_data = sorted(data,
key=lambda x: operator.itemgetter(0)(x['scores']))
print("Sorted by first score:")
for d in sorted_data:
print(f" {d}")
# With tuples
print("\nWith tuples:")
records = [
('Alice', 30, 'NYC'),
('Bob', 25, 'LA'),
('Charlie', 35, 'Chicago')
]
# Sort by age (index 1)
sorted_by_age = sorted(records, key=operator.itemgetter(1))
print("Sorted by age:")
for r in sorted_by_age:
print(f" {r}")
# Sort by multiple fields (city, then age)
sorted_multi = sorted(records, key=operator.itemgetter(2, 1))
print("\nSorted by city then age:")
for r in sorted_multi:
print(f" {r}")
# Map and filter
print("\nMap and filter:")
users = [
{'id': 1, 'name': 'Alice', 'active': True},
{'id': 2, 'name': 'Bob', 'active': False},
{'id': 3, 'name': 'Charlie', 'active': True}
]
# Extract all names
names = list(map(operator.itemgetter('name'), users))
print(f"Names: {names}")
# Extract ids of active users
active_ids = [
operator.itemgetter('id')(user)
for user in users
if user['active']
]
print(f"Active IDs: {active_ids}")
# Min/max
print("\nMin/max:")
products = [
{'name': 'Widget', 'price': 29.99},
{'name': 'Gadget', 'price': 49.99},
{'name': 'Tool', 'price': 19.99}
]
cheapest = min(products, key=operator.itemgetter('price'))
print(f"Cheapest: {cheapest}")
most_expensive = max(products, key=operator.itemgetter('price'))
print(f"Most expensive: {most_expensive}")
# Grouping
print("\nGrouping:")
from itertools import groupby
transactions = [
{'category': 'food', 'amount': 50},
{'category': 'transport', 'amount': 20},
{'category': 'food', 'amount': 30},
{'category': 'transport', 'amount': 15}
]
# Must sort first for groupby
transactions.sort(key=operator.itemgetter('category'))
for category, items in groupby(transactions,
key=operator.itemgetter('category')):
total = sum(operator.itemgetter('amount')(item) for item in items)
print(f"{category}: ${total}")
"""operator.itemgetter examples"""
import operator
# Basic itemgetter
print("Basic itemgetter:")
# Get single item
get_first = operator.itemgetter(0)
numbers =
print(f"get_first({numbers}): {get_first(numbers)}")
# Get by key
data = {'name': 'Alice', 'age': 30}
get_name = operator.itemgetter('name')
print(f"get_name({data}): {get_name(data)}")
# Multiple items
print("\nMultiple items:")
# Get multiple indices
get_items = operator.itemgetter(0, 2, 4)
letters = ['a', 'b', 'c', 'd', 'e']
result = get_items(letters)
print(f"get_items({letters}): {result}")
# Multiple keys
get_info = operator.itemgetter('name', 'age')
person = {'name': 'Bob', 'age': 25, 'city': 'NYC'}
print(f"get_info: {get_info(person)}")
# Sorting lists
print("\nSorting lists:")
students = [
{'name': 'Charlie', 'grade': 85},
{'name': 'Alice', 'grade': 92},
{'name': 'Bob', 'grade': 78}
]
# Sort by grade
sorted_by_grade = sorted(students, key=operator.itemgetter('grade'))
print("Sorted by grade:")
for s in sorted_by_grade:
print(f" {s}")
# Sort by name
sorted_by_name = sorted(students, key=operator.itemgetter('name'))
print("\nSorted by name:")
for s in sorted_by_name:
print(f" {s}")
# Nested sorting
print("\nNested sorting:")
data = [
{'name': 'Alice', 'scores': [85, 90]},
{'name': 'Bob', 'scores': [92, 88]},
{'name': 'Charlie', 'scores': [78, 95]}
]
# Sort by first score
sorted_data = sorted(data,
key=lambda x: operator.itemgetter(0)(x['scores']))
print("Sorted by first score:")
for d in sorted_data:
print(f" {d}")
# With tuples
print("\nWith tuples:")
records = [
('Alice', 30, 'NYC'),
('Bob', 25, 'LA'),
('Charlie', 35, 'Chicago')
]
# Sort by age (index 1)
sorted_by_age = sorted(records, key=operator.itemgetter(1))
print("Sorted by age:")
for r in sorted_by_age:
print(f" {r}")
# Sort by multiple fields (city, then age)
sorted_multi = sorted(records, key=operator.itemgetter(2, 1))
print("\nSorted by city then age:")
for r in sorted_multi:
print(f" {r}")
# Map and filter
print("\nMap and filter:")
users = [
{'id': 1, 'name': 'Alice', 'active': True},
{'id': 2, 'name': 'Bob', 'active': False},
{'id': 3, 'name': 'Charlie', 'active': True}
]
# Extract all names
names = list(map(operator.itemgetter('name'), users))
print(f"Names: {names}")
# Extract ids of active users
active_ids = [
operator.itemgetter('id')(user)
for user in users
if user['active']
]
print(f"Active IDs: {active_ids}")
# Min/max
print("\nMin/max:")
products = [
{'name': 'Widget', 'price': 29.99},
{'name': 'Gadget', 'price': 49.99},
{'name': 'Tool', 'price': 19.99}
]
cheapest = min(products, key=operator.itemgetter('price'))
print(f"Cheapest: {cheapest}")
most_expensive = max(products, key=operator.itemgetter('price'))
print(f"Most expensive: {most_expensive}")
# Grouping
print("\nGrouping:")
from itertools import groupby
transactions = [
{'category': 'food', 'amount': 50},
{'category': 'transport', 'amount': 20},
{'category': 'food', 'amount': 30},
{'category': 'transport', 'amount': 15}
]
# Must sort first for groupby
transactions.sort(key=operator.itemgetter('category'))
for category, items in groupby(transactions,
key=operator.itemgetter('category')):
total = sum(operator.itemgetter('amount')(item) for item in items)
print(f"{category}: ${total}")
attrgetter.py
"""operator.attrgetter examples"""
import operator
from datetime import datetime
# Basic attrgetter
print("Basic attrgetter:")
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person('{self.name}', {self.age})"
# Get single attribute
get_name = operator.attrgetter('name')
person = Person('Alice', 30)
print(f"get_name({person}): {get_name(person)}")
print(f"Equivalent to: {person.name}")
# Multiple attributes
print("\nMultiple attributes:")
# Get multiple attributes
get_info = operator.attrgetter('name', 'age')
result = get_info(person)
print(f"get_info: {result}")
# Sorting objects
print("\nSorting objects:")
people = [
Person('Charlie', 35),
Person('Alice', 30),
Person('Bob', 25)
]
# Sort by name
sorted_by_name = sorted(people, key=operator.attrgetter('name'))
print("Sorted by name:")
for p in sorted_by_name:
print(f" {p}")
# Sort by age
sorted_by_age = sorted(people, key=operator.attrgetter('age'))
print("\nSorted by age:")
for p in sorted_by_age:
print(f" {p}")
# Nested attributes
print("\nNested attributes:")
class Address:
def __init__(self, city, zip_code):
self.city = city
self.zip = zip_code
def __repr__(self):
return f"Address('{self.city}', '{self.zip}')"
class Employee:
def __init__(self, name, address):
self.name = name
self.address = address
def __repr__(self):
return f"Employee('{self.name}', {self.address})"
employees = [
Employee('Alice', Address('NYC', '10001')),
Employee('Bob', Address('LA', '90001')),
Employee('Charlie', Address('Chicago', '60601'))
]
# Access nested attribute
get_city = operator.attrgetter('address.city')
cities = [get_city(emp) for emp in employees]
print(f"Cities: {cities}")
# Sort by nested attribute
sorted_by_city = sorted(employees, key=operator.attrgetter('address.city'))
print("\nSorted by city:")
for emp in sorted_by_city:
print(f" {emp}")
# Min/max
print("\nMin/max:")
class Product:
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
def __repr__(self):
return f"Product('{self.name}', ${self.price}, qty={self.quantity})"
products = [
Product('Widget', 29.99, 100),
Product('Gadget', 49.99, 50),
Product('Tool', 19.99, 200)
]
cheapest = min(products, key=operator.attrgetter('price'))
print(f"Cheapest: {cheapest}")
most_stock = max(products, key=operator.attrgetter('quantity'))
print(f"Most stock: {most_stock}")
# Map operations
print("\nMap operations:")
class Student:
def __init__(self, name, grade):
self.name = name
self.grade = grade
students = [
Student('Alice', 92),
Student('Bob', 85),
Student('Charlie', 78)
]
# Extract all names
names = list(map(operator.attrgetter('name'), students))
print(f"Names: {names}")
# Extract all grades
grades = list(map(operator.attrgetter('grade'), students))
print(f"Grades: {grades}")
# Multiple attributes
info = list(map(operator.attrgetter('name', 'grade'), students))
print(f"Info: {info}")
# Filtering
print("\nFiltering:")
class Task:
def __init__(self, name, priority, completed):
self.name = name
self.priority = priority
self.completed = completed
def __repr__(self):
return f"Task('{self.name}', priority={self.priority}, done={self.completed})"
tasks = [
Task('Review code', 3, False),
Task('Fix bug', 1, True),
Task('Write tests', 2, False)
]
# High priority incomplete tasks
high_priority = [
t for t in tasks
if operator.attrgetter('priority')(t) <= 2 and not t.completed
]
print("High priority incomplete:")
for t in high_priority:
print(f" {t}")
# Grouping
print("\nGrouping:")
from itertools import groupby
class Record:
def __init__(self, category, value):
self.category = category
self.value = value
records = [
Record('A', 10),
Record('B', 20),
Record('A', 15),
Record('B', 25),
Record('A', 5)
]
# Must sort first
records.sort(key=operator.attrgetter('category'))
for category, items in groupby(records,
key=operator.attrgetter('category')):
values = [operator.attrgetter('value')(r) for r in items]
print(f"{category}: {values}, sum={sum(values)}")
# With datetime
print("\nWith datetime:")
class Event:
def __init__(self, name, timestamp):
self.name = name
self.timestamp = timestamp
def __repr__(self):
return f"Event('{self.name}', {self.timestamp})"
events = [
Event('Login', datetime(2024, 1, 15, 10, 30)),
Event('Purchase', datetime(2024, 1, 15, 11, 45)),
Event('Logout', datetime(2024, 1, 15, 9, 15))
]
# Sort chronologically
sorted_events = sorted(events, key=operator.attrgetter('timestamp'))
print("Chronological order:")
for e in sorted_events:
print(f" {e}")
methodcaller.py
"""operator.methodcaller examples"""
import operator
# Basic methodcaller
print("Basic methodcaller:")
# Call method with no arguments
upper = operator.methodcaller('upper')
text = "hello"
print(f"upper('{text}'): {upper(text)}")
print(f"Equivalent to: {text.upper()}")
# Call with arguments
replace_o = operator.methodcaller('replace', 'o', 'x')
result = replace_o("hello world")
print(f"replace_o('hello world'): {result}")
# String methods
print("\nString methods:")
strings = ['hello', 'WORLD', 'Python']
# Map upper
upper_strings = list(map(operator.methodcaller('upper'), strings))
print(f"Upper: {upper_strings}")
# Map lower
lower_strings = list(map(operator.methodcaller('lower'), strings))
print(f"Lower: {lower_strings}")
# Map strip
padded = [' hello ', ' world ', ' python ']
stripped = list(map(operator.methodcaller('strip'), padded))
print(f"Stripped: {stripped}")
# With arguments
print("\nWith arguments:")
# Replace method
texts = ['hello world', 'foo bar', 'baz qux']
replaced = list(map(operator.methodcaller('replace', 'o', 'X'), texts))
print(f"Replace 'o' with 'X': {replaced}")
# Split method
split_lines = list(map(operator.methodcaller('split', ','),
['a,b,c', 'd,e,f', 'g,h,i']))
print(f"Split by comma: {split_lines}")
# Startswith
check_start = operator.methodcaller('startswith', 'hel')
words = ['hello', 'help', 'world', 'helper']
results = [check_start(w) for w in words]
print(f"Startswith 'hel': {list(zip(words, results))}")
# Custom objects
print("\nCustom objects:")
class Counter:
def __init__(self, value=0):
self.value = value
def increment(self, amount=1):
self.value += amount
return self.value
def reset(self):
self.value = 0
return self.value
def __repr__(self):
return f"Counter({self.value})"
counters = [Counter(10), Counter(20), Counter(30)]
# Call reset on all
reset_all = operator.methodcaller('reset')
for c in counters:
reset_all(c)
print(f"After reset: {counters}")
# Increment all by 5
increment_5 = operator.methodcaller('increment', 5)
for c in counters:
increment_5(c)
print(f"After increment(5): {counters}")
# List methods
print("\nList methods:")
lists = [[3, 1, 2], [6, 4, 5], [9, 7, 8]]
# Sort each list
sort_list = operator.methodcaller('sort')
for lst in lists:
sort_list(lst)
print(f"After sort: {lists}")
# Append to each
append_10 = operator.methodcaller('append', 10)
for lst in lists:
append_10(lst)
print(f"After append(10): {lists}")
# Dict methods
print("\nDict methods:")
dicts = [
{'a': 1, 'b': 2},
{'c': 3, 'd': 4},
{'e': 5, 'f': 6}
]
# Get keys from all dicts
get_keys = operator.methodcaller('keys')
all_keys = [list(get_keys(d)) for d in dicts]
print(f"All keys: {all_keys}")
# Get values from all dicts
get_values = operator.methodcaller('values')
all_values = [list(get_values(d)) for d in dicts]
print(f"All values: {all_values}")
# Filtering
print("\nFiltering:")
class Task:
def __init__(self, name, priority):
self.name = name
self.priority = priority
def is_high_priority(self):
return self.priority <= 2
def __repr__(self):
return f"Task('{self.name}', {self.priority})"
tasks = [
Task('Fix bug', 1),
Task('Write docs', 3),
Task('Review code', 2),
Task('Update tests', 4)
]
# Filter using method
is_high = operator.methodcaller('is_high_priority')
high_priority = [t for t in tasks if is_high(t)]
print("High priority tasks:")
for t in high_priority:
print(f" {t}")
# Chaining operations
print("\nChaining operations:")
class Text:
def __init__(self, value):
self.value = value
def upper(self):
return Text(self.value.upper())
def reverse(self):
return Text(self.value[::-1])
def strip(self):
return Text(self.value.strip())
def __repr__(self):
return f"Text('{self.value}')"
text = Text(' hello ')
# Apply operations
operations = [
operator.methodcaller('strip'),
operator.methodcaller('upper'),
operator.methodcaller('reverse')
]
result = text
for op in operations:
result = op(result)
print(f"Original: {text}")
print(f"After operations: {result}")
# With kwargs
print("\nWith kwargs:")
# Split with keyword arguments
split_max = operator.methodcaller('split', ',', maxsplit=2)
result = split_max('a,b,c,d,e')
print(f"Split with maxsplit=2: {result}")
# Format with kwargs
data = {'name': 'Alice', 'age': 30}
format_str = operator.methodcaller('format', **data)
template = "Name: {name}, Age: {age}"
result = format_str(template)
print(f"Formatted: {result}")
arithmetic.py
"""Arithmetic operator functions"""
import operator
from functools import reduce
# Basic arithmetic
print("Basic arithmetic:")
# Addition
print(f"add(5, 3): {operator.add(5, 3)}")
print(f"5 + 3: {5 + 3}")
# Subtraction
print(f"sub(10, 4): {operator.sub(10, 4)}")
# Multiplication
print(f"mul(6, 7): {operator.mul(6, 7)}")
# Division
print(f"truediv(15, 4): {operator.truediv(15, 4)}")
print(f"floordiv(15, 4): {operator.floordiv(15, 4)}")
# Modulo
print(f"mod(17, 5): {operator.mod(17, 5)}")
# Power
print(f"pow(2, 8): {operator.pow(2, 8)}")
# With reduce
print("\nWith reduce:")
numbers = [1, 2, 3, 4, 5]
# Sum using add
total = reduce(operator.add, numbers)
print(f"Sum: {total}")
# Product using mul
product = reduce(operator.mul, numbers)
print(f"Product: {product}")
# Factorial
n = 5
factorial = reduce(operator.mul, range(1, n + 1))
print(f"{n}! = {factorial}")
# Unary operations
print("\nUnary operations:")
# Negation
print(f"neg(5): {operator.neg(5)}")
print(f"neg(-3): {operator.neg(-3)}")
# Positive
print(f"pos(5): {operator.pos(5)}")
print(f"pos(-5): {operator.pos(-5)}")
# Absolute value
print(f"abs(-10): {operator.abs(-10)}")
print(f"abs(7): {operator.abs(7)}")
# String operations
print("\nString operations:")
# String concatenation
result = operator.add("Hello", " World")
print(f"add('Hello', ' World'): {result}")
# String repetition
result = operator.mul("Hi", 3)
print(f"mul('Hi', 3): {result}")
# Join strings with reduce
words = ['Python', 'is', 'awesome']
sentence = reduce(lambda a, b: operator.add(operator.add(a, ' '), b), words)
print(f"Joined: {sentence}")
# List operations
print("\nList operations:")
# List concatenation
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = operator.add(list1, list2)
print(f"add([1,2,3], [4,5,6]): {combined}")
# List repetition
repeated = operator.mul([1, 2], 3)
print(f"mul([1,2], 3): {repeated}")
# Concatenate multiple lists
lists = [[1, 2], [3, 4], [5, 6]]
flattened = reduce(operator.add, lists)
print(f"Flattened: {flattened}")
# Map operations
print("\nMap operations:")
numbers = [1, 2, 3, 4, 5]
# Double all numbers
doubled = list(map(lambda x: operator.mul(x, 2), numbers))
print(f"Doubled: {doubled}")
# Square all numbers
squared = list(map(lambda x: operator.pow(x, 2), numbers))
print(f"Squared: {squared}")
# Negate all numbers
negated = list(map(operator.neg, numbers))
print(f"Negated: {negated}")
# Calculator functions
print("\nCalculator functions:")
def calculate(a, b, op):
"""Apply operator to two numbers"""
return op(a, b)
print(f"calculate(10, 5, add): {calculate(10, 5, operator.add)}")
print(f"calculate(10, 5, sub): {calculate(10, 5, operator.sub)}")
print(f"calculate(10, 5, mul): {calculate(10, 5, operator.mul)}")
print(f"calculate(10, 5, truediv): {calculate(10, 5, operator.truediv)}")
# Operation dispatch
print("\nOperation dispatch:")
operations = {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.truediv,
'%': operator.mod,
'**': operator.pow
}
def eval_expr(a, op, b):
"""Evaluate simple expression"""
return operations[op](a, b)
print(f"10 + 5 = {eval_expr(10, '+', 5)}")
print(f"10 - 5 = {eval_expr(10, '-', 5)}")
print(f"10 * 5 = {eval_expr(10, '*', 5)}")
print(f"10 / 5 = {eval_expr(10, '/', 5)}")
print(f"10 % 3 = {eval_expr(10, '%', 3)}")
print(f"2 ** 8 = {eval_expr(2, '**', 8)}")
# Cumulative operations
print("\nCumulative operations:")
values = [10, -5, 3, -2, 8]
# Cumulative sum
running_sum = []
total = 0
for v in values:
total = operator.add(total, v)
running_sum.append(total)
print(f"Values: {values}")
print(f"Running sum: {running_sum}")
# Cumulative product
running_product = []
product = 1
for v in values:
product = operator.mul(product, v)
running_product.append(product)
print(f"Running product: {running_product}")
# In-place operations
print("\nIn-place operations:")
# iadd (+=)
a = 10
a = operator.iadd(a, 5)
print(f"After iadd(10, 5): {a}")
# imul (*=)
b = 3
b = operator.imul(b, 4)
print(f"After imul(3, 4): {b}")
# List iadd
lst = [1, 2, 3]
lst = operator.iadd(lst, [4, 5])
print(f"List after iadd: {lst}")
comparison.py
"""Comparison operator functions"""
import operator
# Basic comparisons
print("Basic comparisons:")
# Equality
print(f"eq(5, 5): {operator.eq(5, 5)}")
print(f"eq(5, 3): {operator.eq(5, 3)}")
# Not equal
print(f"ne(5, 3): {operator.ne(5, 3)}")
print(f"ne(5, 5): {operator.ne(5, 5)}")
# Less than
print(f"lt(3, 5): {operator.lt(3, 5)}")
print(f"lt(5, 3): {operator.lt(5, 3)}")
# Less than or equal
print(f"le(5, 5): {operator.le(5, 5)}")
print(f"le(3, 5): {operator.le(3, 5)}")
# Greater than
print(f"gt(5, 3): {operator.gt(5, 3)}")
print(f"gt(3, 5): {operator.gt(3, 5)}")
# Greater than or equal
print(f"ge(5, 5): {operator.ge(5, 5)}")
print(f"ge(5, 3): {operator.ge(5, 3)}")
# Filtering
print("\nFiltering:")
numbers = [1, 5, 10, 15, 20, 25]
# Filter >= 10
greater_eq_10 = [x for x in numbers if operator.ge(x, 10)]
print(f"Numbers >= 10: {greater_eq_10}")
# Filter < 15
less_than_15 = [x for x in numbers if operator.lt(x, 15)]
print(f"Numbers < 15: {less_than_15}")
# Filter == 10
equals_10 = list(filter(lambda x: operator.eq(x, 10), numbers))
print(f"Numbers == 10: {equals_10}")
# String comparisons
print("\nString comparisons:")
words = ['apple', 'banana', 'cherry', 'date']
# Equal to 'banana'
is_banana = list(filter(lambda w: operator.eq(w, 'banana'), words))
print(f"Equal to 'banana': {is_banana}")
# Less than 'cherry'
before_cherry = [w for w in words if operator.lt(w, 'cherry')]
print(f"Before 'cherry': {before_cherry}")
# Custom objects
print("\nCustom objects:")
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Person('{self.name}', {self.age})"
people = [
Person('Alice', 30),
Person('Bob', 25),
Person('Charlie', 35)
]
# Find people over 25
over_25 = [p for p in people if operator.gt(p.age, 25)]
print("Over 25:")
for p in over_25:
print(f" {p}")
# Find exactly age 30
age_30 = [p for p in people if operator.eq(p.age, 30)]
print(f"\nAge 30: {age_30}")
# Identity and membership
print("\nIdentity and membership:")
a = [1, 2, 3]
b = [1, 2, 3]
c = a
# Identity (is)
print(f"is_(a, b): {operator.is_(a, b)}")
print(f"is_(a, c): {operator.is_(a, c)}")
# Not identity (is not)
print(f"is_not(a, b): {operator.is_not(a, b)}")
print(f"is_not(a, c): {operator.is_not(a, c)}")
# Containment (in)
print(f"contains([1,2,3], 2): {operator.contains([1, 2, 3], 2)}")
print(f"contains([1,2,3], 5): {operator.contains([1, 2, 3], 5)}")
print(f"contains('hello', 'ell'): {operator.contains('hello', 'ell')}")
# Truth testing
print("\nTruth testing:")
# truth() - test if true
print(f"truth(True): {operator.truth(True)}")
print(f"truth(False): {operator.truth(False)}")
print(f"truth([]): {operator.truth([])}")
print(f"truth([1,2,3]): {operator.truth([1, 2, 3])}")
print(f"truth(0): {operator.truth(0)}")
print(f"truth(42): {operator.truth(42)}")
# not_() - logical not
print(f"not_(True): {operator.not_(True)}")
print(f"not_(False): {operator.not_(False)}")
print(f"not_([]): {operator.not_([])}")
print(f"not_([1,2,3]): {operator.not_([1, 2, 3])}")
# Sorting with comparisons
print("\nSorting with comparisons:")
data = [
{'name': 'Alice', 'score': 85},
{'name': 'Bob', 'score': 92},
{'name': 'Charlie', 'score': 78}
]
# Sort by score descending
from functools import cmp_to_key
def compare_score(a, b):
"""Compare by score (descending)"""
if operator.gt(a['score'], b['score']):
return -1 # a comes first
elif operator.lt(a['score'], b['score']):
return 1 # b comes first
return 0
sorted_data = sorted(data, key=cmp_to_key(compare_score))
print("Sorted by score (desc):")
for d in sorted_data:
print(f" {d}")
# Validation
print("\nValidation:")
def validate_age(age):
"""Validate age is between 0 and 150"""
return operator.ge(age, 0) and operator.le(age, 150)
ages = [25, -5, 30, 200, 45]
for age in ages:
valid = validate_age(age)
print(f"Age {age}: {'valid' if valid else 'invalid'}")
# Range checking
print("\nRange checking:")
def in_range(value, min_val, max_val):
"""Check if value is in range [min, max]"""
return operator.ge(value, min_val) and operator.le(value, max_val)
print(f"in_range(5, 1, 10): {in_range(5, 1, 10)}")
print(f"in_range(15, 1, 10): {in_range(15, 1, 10)}")
print(f"in_range(1, 1, 10): {in_range(1, 1, 10)}")
# Count occurrences
print("\nCount occurrences:")
values = [1, 2, 3, 2, 4, 2, 5]
target = 2
count = sum(1 for v in values if operator.eq(v, target))
print(f"Count of {target}: {count}")
# Count in range
count_range = sum(1 for v in values if operator.ge(v, 2) and operator.le(v, 4))
print(f"Count in [2, 4]: {count_range}")
operator functions
Named functions that perform the same operations as Python operators (+, -, [], .) but can be passed as arguments to other functions.
itemgetter
Creates a callable that retrieves items by key or index - cleaner and faster than lambda x: x['key'] for sorting and mapping.
attrgetter
Creates a callable that retrieves object attributes - supports nested attributes like 'address.city' and multiple attributes.
methodcaller
Creates a callable that invokes a named method with optional arguments - useful for applying the same method across many objects.
Exercise: practical.py
Sort a list of records by multiple fields using itemgetter and attrgetter