To sort a list of objects based on an attribute in Python, use the sorted()
function or the list.sort()
method with the key
parameter. Here’s a detailed explanation with examples:
1. Basic Sorting by a Single Attribute
Use the key
parameter to specify the attribute for comparison.
Example: Sort by a numeric attribute (e.g., age
)
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
people = [
Person("Alice", 30),
Person("Bob", 25),
Person("Charlie", 35)
]
# Sort by age (ascending)
sorted_people = sorted(people, key=lambda x: x.age)
# Output order: Bob (25), Alice (30), Charlie (35)
Sort in descending order:
people.sort(key=lambda x: x.age, reverse=True)
# Output order: Charlie (35), Alice (30), Bob (25)
2. Sorting by a String Attribute (e.g., name
)
# Sort alphabetically by name (case-sensitive)
sorted_people = sorted(people, key=lambda x: x.name)
# Output order: Alice, Bob, Charlie
# Sort case-insensitively
sorted_people = sorted(people, key=lambda x: x.name.lower())
3. Sorting by Multiple Attributes
Use a tuple in the key
function to prioritize attributes.
Example: Sort by age
first, then name
people = [
Person("Alice", 30),
Person("David", 30),
Person("Bob", 25),
Person("Charlie", 35)
]
# Sort by age (ascending), then name (ascending)
sorted_people = sorted(people, key=lambda x: (x.age, x.name))
# Output order: Bob (25), Alice (30), David (30), Charlie (35)
4. Using operator.attrgetter
for Cleaner Code
The attrgetter
function from the operator
module simplifies attribute access.
from operator import attrgetter
# Sort by age
sorted_people = sorted(people, key=attrgetter('age'))
# Sort by multiple attributes
sorted_people = sorted(people, key=attrgetter('age', 'name'))
5. Sorting Custom Objects with __lt__
(Advanced)
Implement the __lt__
method in your class to define natural ordering.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __lt__(self, other):
return self.age < other.age # Sort by age by default
people = [Person("Alice", 30), Person("Bob", 25)]
people.sort() # Uses __lt__ to compare
6. Handling Edge Cases
Missing Attributes
Ensure all objects have the attribute used for sorting, or handle exceptions:
try:
sorted_people = sorted(people, key=lambda x: x.age)
except AttributeError:
print("One or more objects lack the 'age' attribute!")
None Values
Use a default value for None
attributes:
sorted_people = sorted(people, key=lambda x: x.age if x.age is not None else 0)
Full Example Workflow
from operator import attrgetter
class Book:
def __init__(self, title, author, year):
self.title = title
self.author = author
self.year = year
books = [
Book("The Hobbit", "J.R.R. Tolkien", 1937),
Book("1984", "George Orwell", 1949),
Book("Brave New World", "Aldous Huxley", 1932)
]
# Sort by publication year (ascending)
sorted_books = sorted(books, key=attrgetter('year'))
# Output: Brave New World (1932), The Hobbit (1937), 1984 (1949)
# Sort by author name (case-insensitive), then title
sorted_books = sorted(
books,
key=lambda x: (x.author.lower(), x.title)
)
Summary Table
Task | Code Example |
---|---|
Sort by single attribute | sorted(list, key=lambda x: x.attr) |
Sort descending | sorted(list, key=..., reverse=True) |
Sort by multiple attrs | key=lambda x: (x.attr1, x.attr2) |
Use attrgetter | from operator import attrgetter; key=attrgetter('attr') |
This approach works for any object with accessible attributes, including dataclasses, SQLAlchemy models, or custom classes!