How to Use sorted() and sort() in Python

How to Use sorted() and .sort() in Python

by David Fundakowski Feb 24, 2025 basics python

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Sorting Data With Python

Sorting in Python is a fundamental task that you can accomplish using sorted() and .sort(). The sorted() function returns a new sorted list from the elements of any iterable, without modifying the original iterable. On the other hand, the .sort() method modifies a list in place and doesn’t return a value. Both methods support customization through optional keyword arguments like key and reverse.

By the end of this tutorial, you’ll understand that:

  • You can sort any iterable with the sorted() function.
  • The sorted() function returns a new sorted list.
  • The .sort() method sorts the list in place.
  • You sort items in descending order by setting the reverse argument to True.
  • The key argument accepts a function to customize the sort order.

In this tutorial, you’ll learn how to sort various types of data in different data structures, customize the order, and work with two different ways of sorting in Python. You’ll need a basic understanding of lists and tuples as well as sets. These are the data structures you’ll be using to perform some basic operations.

Take the Quiz: Test your knowledge with our interactive “How to Use sorted() and .sort() in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Use sorted() and .sort() in Python

In this quiz, you'll test your understanding of sorting in Python using sorted() and .sort(). You'll revisit how to sort various types of data in different data structures, customize the order, and work with two different ways of sorting in Python.

Ordering Values With sorted()

In Python, you can sort iterables with the sorted() built-in function. To get started, you’ll work with iterables that contain only one data type.

Sorting Numbers

You can use sorted() to sort a list in Python. In this example, a list of integers is defined, and then sorted() is called with the numbers variable as the argument:

Python
>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers)
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

The output from this code is a new, sorted list. When the original variable is printed, the initial values are unchanged.

This example shows four important characteristics of sorted():

  1. You don’t have to define the sorted() function. It’s a built-in function that’s available in any standard installation of Python.
  2. You’re ordering the values in numbers from smallest to largest when you call sorted(numbers). When you pass no additional arguments or parameters, sorted() orders the values in numbers in ascending order.
  3. You don’t change the original numbers variable because sorted() provides sorted output and doesn’t update the original value in place.
  4. You get an ordered list as a return value when you call sorted().

These points mean that sorted() can be used on a list, and the output can immediately be assigned to a variable:

Python
>>> numbers = [6, 9, 3, 1]
>>> numbers_sorted = sorted(numbers)
>>> numbers_sorted
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

In this example, a new variable called numbers_sorted now stores the output of the sorted() function.

You can confirm all of these observations by calling help() on sorted():

Python
>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

You’ll cover the optional arguments key and reverse later in the tutorial.

The first parameter of sorted() is an iterable. That means that you can use sorted() on tuples and sets very similarly:

Python
>>> numbers_tuple = (6, 9, 3, 1)
>>> sorted(numbers_tuple)
[1, 3, 6, 9]

>>> numbers_set = {5, 10, 1, 0}
>>> sorted(numbers_set)
[0, 1, 5, 10]

Notice how even though the input was a set and a tuple, the output is a list because sorted() returns a new list by definition. The returned object can be cast to a new type if it needs to match the input type. Be careful if attempting to cast the resulting list back to a set, as a set by definition is unordered:

Python
>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]
>>> tuple(numbers_tuple_sorted)
(1, 3, 6, 9)
>>> set(numbers_set_sorted)
{0, 1, 10, 5}

When you cast the numbers_set_sorted value to a set, it’s unordered, as expected. If you’re curious about how sets work in Python, then you can check out the tutorial Sets in Python.

Sorting Strings

Just like lists, tuples, and sets, strings are also iterables. This means you can sort str types as well. The example below shows how sorted() iterates through each character in the value passed to it and orders them in the output:

Python
>>> string_number_value = "34521"
>>> sorted(string_number_value)
['1', '2', '3', '4', '5']

>>> string_value = "I like to sort"
>>> sorted(string_value)
[' ', ' ', ' ', 'I', 'e', 'i', 'k', 'l', 'o', 'o', 'r', 's', 't', 't']

Just like before, you can use sorted() to iterate through each element of the iterable you pass in. In a string, each element means each character, including spaces.

If you want to sort a sentence by words, then you can use Python’s .split() method:

Python
>>> string_value = "I like to sort"
>>> sorted_string = sorted(string_value.split())
>>> sorted_string
['I', 'like', 'sort', 'to']

In this example, you use .split() to convert the original sentence into a list of words. Afterward, you sort the list instead of individual characters.

Exploring Limitations and Gotchas With Python Sorting

When sorting objects in Python, you may run into some unexpected behavior or even errors. In this section, you’ll explore some limitations and gotchas to look out for when using Python’s sorted() function.

Handling Lists With Non-Comparable Data Types

There are data types that can’t be compared to each other using sorted() because they’re too different. Python will return an error if you attempt to use sorted() on a list containing non-comparable data. In the example below, you have None and the integer zero (0) in the same list. Python doesn’t know how to sort these two types because of their incompatibility:

Python
>>> mixed_types = [None, 0]
>>> sorted(mixed_types)
Traceback (most recent call last):
  ...
TypeError: '<' not supported between instances of 'int' and 'NoneType'

This error shows why Python can’t sort the values given to it. It’s trying to put the values in order by using the less than operator (<) to determine which value is lower in sorting order. You can replicate this error by manually comparing the two values:

Python
>>> None < 0
Traceback (most recent call last):
  ...
TypeError: '<' not supported between instances of 'NoneType' and 'int'

The same TypeError is thrown when you try to compare two non-comparable values without using sorted().

If the values in the list can be compared without raising a TypeError, then the list can be sorted. This prevents sorting iterables with intrinsically unorderable values and producing output that may not make sense.

Python can implicitly convert a value to another type. Even though elements in a list look different, Python may able to interpret them as integers and compare them to each other using sorted():

Python
>>> sorted([1, False, True, 0])
[False, 0, 1, True]

Python interprets the Boolean False as 0 and True as 1. You can verify that Python considers the integers 0 and 1 equal to False and True by comparing them manually:

Python
>>> 0 == False
True

>>> 1 == True
True

If you have a look at the ordered list from before, you can spot another important aspect of sorting called sort stability. In Python, when you sort equal values, they’ll retain their original order in the output. Since the integer 1 comes before True in the unsorted list, 1 will appear before True in the sorted list.

Considering Length When Sorting Similar Strings

In the example above, you were sorting either single characters or different words. When dealing with a list that contains similar strings, Python sorts shorter strings first:

Python
>>> sorted(["aaa", "a"])
['a', 'aaa']

Strings that contain identical values will end up being sorted shortest to longest because the shorter strings lack elements to compare against the longer ones.

This doesn’t mean that shorter strings always come first:

Python
>>> sorted(["aaa", "ab", "a"])
['a', 'aaa', 'ab']

If the first letter is the same, then sorted() will use the second character to determine order, and so on.

In the example above, ab is shorter than aaa. But while traversing through the string to determine how to sort ab compared to aaa, the second letter of ab is considered larger than the second letter of aaa. That’s because the letter b has a larger Unicode than the letter a.

You can leverage Python’s ord() function to investigate a character’s Unicode:

Python
>>> ord("b")
98

>>> ord("a")
97

To learn more about some of Python’s quirks when ordering strings, check out the tutorial How to Sort Unicode Strings Alphabetically in Python.

Customizing sorted() With Keyword Arguments

When using Python’s sorted() function, you can optionally pass in values for the keywords reverse and key. This enables you to override the default behavior of sorted() and customize the order of the output.

Sorting Iterables in Reverse Order

As the name suggests, the keyword argument reverse let’s you reverse the order of an iterable. The reverse keyword accepts a Boolean value:

Python
>>> numbers = [10, 3, 7]
>>> sorted(numbers)
[3, 7, 10]
>>> sorted(numbers, reverse=True)
[10, 7, 3]

The default value of reverse is False, which results in the ascending order of items. If you set reverse to True, then the sorting will be in descending order.

Sorting Strings by Length

One of the most powerful components of sorted() is the keyword argument called key. This argument expects a function to be passed to it, and that function will be used on each value in the list being sorted to determine the resulting order.

To demonstrate a basic example, let’s assume the requirement for ordering a specific list is the length of the strings in the list, from shortest to longest. You can use the len() function to return the length of a string, along with the key argument:

Python
>>> word = "paper"
>>> len(word)
5

>>> words = ["banana", "pie", "Washington", "book"]
>>> sorted(words, key=len)
['pie', 'book', 'banana', 'Washington']

The resulting order is a list with a string order of shortest to longest. The length of each element in the list is determined by len() and then returned in ascending order.

Ignoring the Case When Sorting Strings

By default, sorting in Python is case sensitive. This means that words starting with an uppercase Z will be sorted before those beginning with lowercase letters because of their Unicode values:

Python
>>> sorted(["ape", "Zebra", "elephant"])
['Zebra', 'ape', 'elephant']

You can pass in str.lower as the value of key to sort strings independently of a character’s case:

Python
>>> sorted(["ape", "Zebra", "elephant"], key=str.lower)
['ape', 'elephant', 'Zebra']

During sorting, the function passed to key is called on each element to determine sort order, but the original values remain in the output.

Avoiding Pitfalls When Using sorted() With a key Argument

There are two main limitations to look out for when you’re using functions with the key argument.

First, the number of required arguments in the function passed to key must be exactly one:

Python
>>> def add(x, y):
...     return x + y
...

>>> sorted([1, 2, 3], key=add)
Traceback (most recent call last):
  ...
TypeError: add() missing 1 required positional argument: 'y'

The example above shows the definition of an addition function that takes two arguments. When that function is used in key on a list of numbers, it fails because it’s missing a second argument. Each time add() is called during the sort, it’s only receiving one element from the list at a time.

The second limitation of key is that the function used with key must be able to handle all the values in the iterable.

Here, you have a list of numbers represented as strings to be used in sorted(), and key is going to attempt to convert them to numbers using int:

Python
>>> values_to_cast = ["11", "3", "2"]
>>> sorted(values_to_cast, key=int)
['2', '3', '11']

However, if a value in the iterable can’t be cast to an integer, then using int as the value for key will fail:

Python
>>> values_to_cast = ["11", "3", "2", "A"]
>>> sorted(values_to_cast, key=int)
Traceback (most recent call last):
  ...
ValueError: invalid literal for int() with base 10: 'A'

As long as a string contains a numeric value, Python can convert the string to an integer. Since A isn’t a numeric value, you receive a ValueError when calling sorted() with key=int.

Combining sorted() With lambda Functions

The key functionality is extremely powerful because it allows you to manipulate the output order using almost any function, whether built-in or user-defined.

If the ordering requirement is to order an iterable by each string spelled backwards, then you could define a function that reverses a word.

In the example below, you define a function named reverse_word() that reverses the string passed to it. Then, you use reverse_word as the value of key when calling sorted():

Python
>>> def reverse_word(word):
...     return word[::-1]
...
>>> words = ["cookie", "banana", "donut", "pizza"]
>>> sorted(words, key=reverse_word)
['banana', 'pizza', 'cookie', 'donut']

The word[::-1] slice syntax reverses a string. Each element will have reverse_word() applied to it, and the sorting order will be based on the characters in the reversed version of each word. If two words have the same final letter, the next letter is compared, and so on.

As a result, the elements in words are sorted based on their ending letters, which is why "pizza" comes before "cookie" but after "banana".

Instead of writing a standalone function, you can shorten the code and leverage the lambda keyword. With lambda, you can create an anonymous function, commonly refered to as a lambda function.

By using lambda, you can define a function inline and use it directly as the value of key. Instead of defining and calling reverse_word(), you can accomplish the same result with fewer lines of code:

Python
>>> words = ["cookie", "banana", "donut", "pizza"]
>>> sorted(words, key=lambda word: word[::-1])
['banana', 'pizza', 'cookie', 'donut']

In the example above, the key is defined as a lambda. The lambda function takes one argument named word. Then, word[::-1] is called on each element and reverses the word. That reversed output is then used for sorting, but the original words are still returned.

Ordering Values With .sort()

So far, you’ve learned about Python’s sorted() function. However, you may have come across a method with a similar name—the .sort() method:

Python
>>> help(list.sort)
Help on method_descriptor:

sort(self, /, *, key=None, reverse=False) unbound builtins.list method
    Sort the list in ascending order and return None.

    The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
    order of two equal elements is maintained).

    If a key function is given, apply it once to each list item and sort them,
    ascending or descending, according to their function values.

    The reverse flag can be set to sort in descending order.

At first glance, the description of .sort() looks similar to the output of help(sorted), which you explored earlier. Before taking a look at the similarities between .sort() and sorted(), it’s important to first understand their differences.

Understanding the Differences Between .sort() and sorted()

The .sort() method accomplishes more or less the same thing as the sorted() function. But there are four critical differences between .sort() and sorted():

  1. .sort() is a method of the list class.
  2. .sort() can only be used with lists.
  3. .sort() returns None.
  4. .sort() modifies the order of elements in place.

As a method, .sort() works with the list instance itself. In other words, you don’t explicitly pass in an iterable as an argument.

Have a look at the impacts of these differences in code:

Python
>>> tuple_val = (5, 1, 3, 5)
>>> tuple_val.sort()
Traceback (most recent call last):
  ...
AttributeError: 'tuple' object has no attribute 'sort'

>>> values_to_sort = list(tuple_val)
>>> returned_from_sort = values_to_sort.sort()
>>> print(returned_from_sort)
None

>>> print(values_to_sort)
[1, 3, 5, 5]

When you try calling .sort() with a tuple, you get an AttributeError because .sort() only exists for lists.

Then, there are some other pretty dramatic differences in how .sort() operates compared to sorted() in this code example:

  1. .sort() returns None, so the assignment to returned_from_sort is None and not an ordered list.
  2. Calling .sort() changes the values_to_sort list in place, and the original order is not maintained in any way.

These differences in behavior make .sort() and sorted() absolutely not interchangeable in code, and they can produce wildly unexpected outcomes if one is used in the wrong way.

Using Keywords Arguments With .sort() and sorted()

The .sort() method has the same key and reverse optional keyword arguments that produce the same robust functionality as sorted().

Revisit some examples from before, this time using .sort() instead of sorted():

Python
>>> numbers = [10, 3, 7]
[3, 7, 10]
>>> numbers.sort(reverse=True)
>>> numbers
[10, 7, 3]

Just like when you used sorted(), if you set reverse to True when calling .sort() on a list, then the sorting will be in descending order.

When you pass in str.lower as the value of key, you can sort strings independently of a character’s case:

Python
>>> animals = ["ape", "Zebra", "elephant"]
>>> animals.sort(key=str.lower)
>>> animals
['ape', 'elephant', 'Zebra']

During sorting, the function passed to key is being called on each element to determine the sort order.

If you want to practice using .sort(), then try refactoring the sorted() examples from earlier sections with .sort(). When doing so, keep in mind that .sort() only works with lists.

Deciding When to Use sorted() vs .sort()

If you’re sorting an iterable that isn’t a list, then you must use sorted(). But if you’re working with a list, then you can use either sorted() or .sort().

Generally, if you keep the similarities and differences in mind, then you can use either sorted() or .sort(). However, there can be situations where it’s important to choose the right tool for the task at hand.

Let’s say there’s a 5K race coming up and you need to capture and sort the race data. The data that needs to be captured is the runner’s bib number and the number of seconds it took to finish the race.

To keep things tidy, you decide to use a named tuple for convenient access:

Python
>>> from collections import namedtuple

>>> Runner = namedtuple("Runner", "bib_number duration")

As the runners cross the finish line, each Runner will be added to a list called runners. In 5K races, not all runners start at the same time, so the first person to cross the finish line might not actually be the fastest person:

Python
>>> runners = []
>>> runners.append(Runner("2528567", 1500))
>>> runners.append(Runner("7575234", 1420))
>>> runners.append(Runner("2666228", 1600))
>>> runners.append(Runner("2425201", 1490))
>>> runners.append(Runner("1235277", 1620))
>>> # Thousands and Thousands of entries later...
>>> runners.append(Runner("2526674", 1906))

Each time a runner crosses the finish line, you add their bib number and total duration in seconds to the runners list.

The top five fastest participants are the winners that get prizes, and the remaining runners will be sorted by fastest time. There are no requirements for multiple types of sorting by various attributes. The list is a reasonable size, and there’s no mention of storing the list somewhere.

In other words, you need to sort runners by duration and grab the five participants with the lowest duration:

Python
>>> runners.sort(key=lambda runner: runner.duration)
>>> top_five_runners = runners[:5]

You use a lambda in the key argument to get the duration attribute from each runner and sort runners in place using .sort(). After runners is sorted, you store the first five elements in top_five_runners.

Mission accomplished—or so you think!

The race director now informs you that every forty-second runner to cross the finish line will receive a free gym bag.

That’s a problem! By using .sort(), you changed runners irreversibly. There’s no way to recover the original list of runners in the order they finished and find every forty-second person.

In hindsight, you should’ve sorted the runners with sorted() and used the same lambda:

Python
>>> runners_by_duration = sorted(runners, key=lambda runner: runner.duration)
>>> top_five_runners = runners_by_duration[:5]

By using sorted(), you can keep the original list of runners intact without overwriting it. This means that you can now find every forty-second person that crosses the finish line:

Python
>>> gym_bag_winners = runners[::42]

You create the gym_bag_winners list by leveraging the slice syntax on runners, which still contains the original order of runners who cross the finish line.

If you’re working with important data and there’s even a remote possibility that you might need to recover the original order, then using .sort() is not the best option. However, if the data is a copy, unimportant information, or data that can be easily re-created, then .sort() can be a fine option.

Conclusion

The .sort() method and sorted() function can provide exactly the sort order you need if you use them properly with both the reverse and key optional keyword arguments.

Both have different characteristics when it comes to output and in-place modifications, so make sure you think through any application functionality or program requirements before choosing your approach.

Frequently Asked Questions

Now that you have some experience with sorting in Python, you can use the questions and answers below to check your understanding and recap what you’ve learned.

These FAQs are related to the most important concepts you’ve covered in this tutorial. Click the Show/Hide toggle beside each question to reveal the answer.

You can sort a list in Python using either sorted() or .sort(). For example, calling sorted(words) or words.sort().

The .sort() method works only with lists, while the sorted() function can be used with any iterable.

The .sort() method sorts a list in place and returns None, whereas sorted() creates a new sorted list and doesn’t alter the original data.

You can sort numbers in descending order by passing the reverse=True argument to either sorted() or .sort(). This argument will reverse the order, showing the larger numbers first.

The key argument allows you to specify a function to be called on each list element prior to making comparisons, enabling customized sorting based on specific criteria.

You can’t sort a list with non-comparable data types directly, as Python will raise a TypeError. All elements must be comparable, or you need a custom key function to handle the comparison.

Take the Quiz: Test your knowledge with our interactive “How to Use sorted() and .sort() in Python” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

How to Use sorted() and .sort() in Python

In this quiz, you'll test your understanding of sorting in Python using sorted() and .sort(). You'll revisit how to sort various types of data in different data structures, customize the order, and work with two different ways of sorting in Python.

Watch Now This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Sorting Data With Python

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About David Fundakowski

David is a Python developer with a background in database administration and development. He currently owns equipment to brew coffee 6 different ways.

» More about David

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!