The sorted( ) function sorts the elements of a given iterable in ascending or descending order and returns it as a list.

### Syntax:

The `sorted()`

function has the following syntax:

`sorted(iterable, key=None, reverse=False)`

### Parameters:

sorted( ) function can take three parameters.

**iterable**: The sequence of items (list, tuple, string, etc.) or collection (set, dictionary, etc.) to sort.**key**(optional): A function that serves as a key for the sort comparison. This parameter is not to modify the objects you’re sorting; instead, it specifies a method to extract a comparison key from each list element.**reverse**(optional): A boolean value. If set to`True`

, the sorted list is reversed (or sorted in descending order).

### Return Value:

The `sorted()`

function returns a new sorted list from the items in the iterable.

### How sorted() Work in Python?

To understand how `sorted()`

works, let’s look at a simple example:

### Sorting a Python list using sorted()

```
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # Output: [1, 1, 2, 3, 4, 5, 6, 9]
```

In the example above, `sorted()`

takes the list `numbers`

and returns a new list with the elements sorted in ascending order.

### Custom Sorting With key Parameter

The real power of `sorted()`

lies in its `key`

parameter, which allows for custom sorting. The `key`

parameter accepts a function to be called on each list element prior to making comparisons.

#### Sorting by Length of Items

For instance, to sort a list of strings by their length:

```
words = ["banana", "pie", "Washington", "book"]
sorted_words = sorted(words, key=len)
print(sorted_words) # Output: ['pie', 'book', 'banana', 'Washington']
```

#### Sorting by a Custom Function

You can also define your own function:

```
def get_second_element(item):
return item[1]
pairs = [(1, 3), (3, 2), (2, 1)]
sorted_pairs = sorted(pairs, key=get_second_element)
print(sorted_pairs) # Output: [(2, 1), (3, 2), (1, 3)]
```

#### Using a Lambda Function

For convenience, a lambda function is often used with `sorted()`

:

```
pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
sorted_by_second = sorted(pairs, key=lambda pair: pair[1])
print(sorted_by_second) # Output: [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
```

### Sorting in Reverse

By setting the `reverse`

parameter to `True`

, you can sort the items in descending order:

```
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
sorted_numbers_desc = sorted(numbers, reverse=True)
print(sorted_numbers_desc) # Output: [9, 6, 5, 4, 3, 2, 1, 1]
```

### Sorting Without Changing the Original Iterable

One of the advantages of using `sorted()`

is that it creates a new list and does not change the original iterable. This is particularly useful when the original order needs to be preserved for later use.

### Complex Sorts: Sorting by Multiple Keys

Sorting by multiple keys involves ordering a collection of items based on more than one criterion. In Python, when you pass a function to the `key`

argument in `sorted()`

, that function is used to generate a sorting key for each element in the iterable. When you want to sort by multiple keys, you can have the function return a tuple that represents the priority of each sort key.

Let’s work through an example where we have a list of records for students. Each record contains the student’s name, grade, and age. Our goal is to sort the list first by grade in descending order, then by age in ascending order, and finally by name in ascending order.

Here is how we might do this:

```
students = [
('John', 'Grade 4', 12),
('Anna', 'Grade 3', 9),
('Barry', 'Grade 4', 10),
('Daisy', 'Grade 3', 11),
('Cindy', 'Grade 4', 10),
('Charlie', 'Grade 3', 9),
('Fred', 'Grade 4', 12)
]
# Our key function will return a tuple where we first take the grade and multiply by -1
# because we want to sort grades in descending order.
# Then we take the age for ascending order,
# and finally the name for alphabetical order.
def sort_key(record):
grade = int(record[1].split(' ')[1]) # Extract the grade number (int) from the string.
age = record[2]
name = record[0]
return (-grade, age, name)
sorted_students = sorted(students, key=sort_key)
for student in sorted_students:
print(student)
```

Output:

```
('Barry', 'Grade 4', 10)
('Cindy', 'Grade 4', 10)
('Fred', 'Grade 4', 12)
('John', 'Grade 4', 12)
('Anna', 'Grade 3', 9)
('Charlie', 'Grade 3', 9)
('Daisy', 'Grade 3', 11)
```

### sorted() with Custom Objects

You can even sort a list of custom objects by defining a `__lt__`

method that `sorted()`

will use or by providing a `key`

function that returns a property to sort by.

```
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f'{self.name} ({self.age})'
people = [Person('Alice', 30), Person('Bob', 25), Person('Charlie', 35)]
sorted_people = sorted(people, key=lambda p: p.age)
print(sorted_people) # Output: [Bob (25), Alice (30), Charlie (35)]
```

### Performance Considerations

The `sorted()`

function is implemented using the Timsort algorithm, which is very efficient for real-world data. It has O(n log n) time complexity on average. However, when sorting large datasets, it’s important to consider the complexity of the `key`

function.

### When Not to Use sorted()

- When you only need the minimum or maximum element, consider using
`min()`

or`max()`

, which are more efficient. - If you’re repeatedly sorting the same list, it may be more efficient to sort it once with
`list.sort()`

and then use the list as needed.

### Conclusion

The `sorted()`

function is a powerful and versatile tool in Python that simplifies the task of sorting various types of data. By understanding and utilizing its `key`

and `reverse`

parameters effectively, developers can perform complex sorts succinctly and efficiently. Its non-destructive nature preserves original data, allowing for greater flexibility in data manipulation. Whether working with simple lists or complex objects, `sorted()`

provides a robust solution for organizing data in Python.