Python Set Comprehensions: How and When to Use Them

Python Set Comprehensions: How and When to Use Them

by Leodanis Pozo Ramos Dec 11, 2024 intermediate python

Python set comprehensions provide a concise way to create and manipulate sets in your code. They generate sets with a clean syntax, making your code more readable and Pythonic. With set comprehensions, you can create, transform, and filter sets, which are great skills to add to your Python programming toolkit.

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

  • Python has set comprehensions, which allow you to create sets with a concise syntax.
  • Python has four types of comprehensions: list, set, dictionary, and generator expressions.
  • A set comprehension can be written as {expression for item in iterable [if condition]}.
  • Sets can’t contain duplicates, as they ensure that all their elements are unique.

To get the most out of this tutorial, you should be familiar with basic Python concepts such as for loops, iterables, list comprehensions, and dictionary comprehensions.

Take the Quiz: Test your knowledge with our interactive “Python Set Comprehensions: How and When to Use Them” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python Set Comprehensions: How and When to Use Them

In this quiz, you'll test your understanding of Python set comprehensions. Set comprehensions are a concise and quick way to create, transform, and filter sets in Python. They can significantly enhance your code's conciseness and readability compared to using regular for loops to process your sets.

Creating and Transforming Sets in Python

In Python programming, you may need to create, populate, and transform sets. To do this, you can use set literals, the set() constructor, and for loops. In the following sections, you’ll take a quick look at how to use these tools. You’ll also learn about set comprehensions, which are a powerful way to manipulate sets in Python.

Creating Sets With Literals and set()

To create new sets, you can use literals. A set literal is a series of elements enclosed in curly braces. The syntax of a set literal is shown below:

Python Syntax
{element_1, element_2,..., element_N}

The elements must be hashable objects. The objects in the literal might be duplicated, but only one instance will be stored in the resulting set. Sets don’t allow duplicate elements. Here’s a quick example of a set:

Python
>>> colors = {"blue", "red", "green", "orange", "green"}
>>> colors
{'red', 'green', 'orange', 'blue'}

>>> colors.add("purple")
>>> colors
{'red', 'green', 'orange', 'purple', 'blue'}

In this example, you create a set containing color names. The elements in your resulting set are unique string objects. You can add new elements using the .add() method. Remember that sets are unordered collections, so the order of elements in the resulting set won’t match the insertion order in most cases.

You can also create a new set using the set() constructor and an iterable of objects:

Python
>>> numbers = [2, 2, 1, 4, 2, 3]

>>> set(numbers)
{1, 2, 3, 4}

In this example, you create a new set using set() with a list of numeric values. Note how the resulting set doesn’t contain duplicate elements. In practice, the set() constructor is a great tool for eliminating duplicate values in iterables.

To create an empty set, you use the set() constructor without arguments:

Python
>>> set()
set()

You can’t create an empty set with a literal because a pair of curly braces {} represents an empty dictionary, not a set. To create an empty set, you must use the set() constructor.

Using for Loops to Populate Sets

Sometimes, you need to start with an empty set and populate it with elements dynamically. To do this, you can use a for loop. For example, say that you want to create a set of unique words from a text. Here’s how to do this with a loop:

Python
>>> unique_words = set()

>>> text = """
... Beautiful is better than ugly
... Explicit is better than implicit
... Simple is better than complex
... Complex is better than complicated
... """.lower()

>>> for word in text.split():
...     unique_words.add(word)
...

>>> unique_words
{
    'beautiful',
    'ugly',
    'better',
    'implicit',
    'complicated',
    'than',
    'explicit',
    'is',
    'complex',
    'simple'
}

In this example, you first create an empty set using set(). You apply lowercase to the text using the .lower() method to make the word extraction case insensitive. Then, you run a loop over a list of words extracted from the text.

As a quick approach, you’ve used the .split() method to split the text into individual words using the space character as a separator.

The loop attempts to add a word to the set in each iteration. However, if a word is already in the set, then any new instance won’t be added. That’s why the resulting set only has one instance of better, for example. The loop is readable and clear, but you can use a set comprehension to make your code even more concise.

Introducing Set Comprehensions

Set comprehensions allow you to build sets with a one-line for loop. If you’re familiar with list comprehensions, then you’ll quickly grasp set comprehensions. Both constructs have similar syntax. The main difference is that set comprehensions use curly braces instead of square brackets.

Here’s the syntax for a set comprehension:

Python Syntax
{expression for member in iterable [if condition]}

A set comprehension returns a new set. To build this set, you compute the elements from the items of an input iterable. The syntax includes an optional conditional at the end, which you can use to filter existing collections or generate elements conditionally.

The set comprehension syntax consists of four key elements:

  1. Enclosing brackets: Curly braces ({}) are used to define set comprehensions.
  2. The comprehension expression: An expression that provides an element in each iteration.
  3. The current member: This is the name of the current item or value in the iterable.
  4. The iterable: This can be any Python iterable object including a list, tuple, set, generator, or similar types.

The following code shows how you can build a set of unique words using a comprehension:

Python
>>> text = """
... Beautiful is better than ugly
... Explicit is better than implicit
... Simple is better than complex
... Complex is better than complicated
... """.lower()

>>> {word for word in text.split()}
{
    'beautiful',
    'ugly',
    'better',
    'implicit',
    'complicated',
    'than',
    'explicit',
    'is',
    'complex',
    'simple'
}

In this example, you use a set comprehension to extract unique words from the original text. The syntax is concise and clear, improving the readability of your code.

In practice, when you don’t need to transform the data to generate the elements of your set, you can replace the loop from the previous section and the above comprehension with the following code:

Python
>>> set(text.split())
{
    'beautiful',
    'ugly',
    'better',
    'implicit',
    'complicated',
    'than',
    'explicit',
    'is',
    'complex',
    'simple'
}

In this example, you pass the split text directly to the set() constructor and get the same result as with the loop or comprehension. You can do this because the set elements don’t need to run through a transformation.

Comprehensions can also include more than one for clause. When they do, the leftmost for iterates over the outer collection, the next for from left to right iterates over the first nesting level, and so on.

To illustrate, say that you have a list of lists. Each nested list contains numbers, and you want to create a set with their square values. To do this, you can use a comprehension with two for clauses as shown below:

Python
>>> matrix = [
...     [9, 3, 8, 3],
...     [4, 5, 2, 8],
...     [6, 4, 3, 1],
...     [1, 0, 4, 5],
... ]

>>> {value**2 for row in matrix for value in row}
{64, 1, 0, 4, 36, 9, 16, 81, 25}

In this example, the first for loop iterates over the rows of your matrix. The second for loop iterates over the number in each row. As a result, you get a set of square values.

It’s important to note that in this example, instead of having 16 elements, you end up with only nine. This is because set elements are unique. When an element is duplicated, the new instance isn’t added to the final set.

Leveraging Set Comprehensions in Python

With set comprehensions, you can create new sets, transform existing ones, and even filter elements using conditionals. In the following sections, you’ll learn how to use set comprehension to approach these use cases.

To begin with, you’ll learn how to use comprehensions to create new sets from existing iterables.

Creating Sets From Iterables

Sometimes, you have an iterable of data and want to create a set using the data items to generate the elements through some data transformation.

For example, say you have a list of tools and libraries. You need to continually check whether a given tool is on the list. To do this, you use membership tests. You also need to make your code case insensitive, so you decide to transform all the words into lowercase letters.

Sets are more efficient than lists in membership tests. Therefore, you also decide to convert your list of tools into a set of lowercase words:

Python
>>> tools = ["Python", "Django", "Flask", "pandas", "NumPy"]

>>> tools_set = {tool.lower() for tool in tools}
>>> tools_set
{'django', 'numpy', 'flask', 'pandas', 'python'}

>>> "python".lower() in tools_set
True
>>> "Pandas".lower() in tools_set
True
>>> "Numpy".lower() in tools_set
True

In the highlighted line, you use a set comprehension while normalizing all values to lowercase to ensure consistent comparisons. Then, you use the in operator to run membership tests and determine whether a given tool is in your original list.

Again, if you don’t need to apply any data transformation to the items of the input iterable, then you don’t have to use a set comprehension. You can use set(iterable) instead. In the above example, the transformation consists of turning the tool names into lowercase.

Transforming Existing Sets

You can also use set comprehensions to quickly transform existing sets. Say that you have a set of user-entered email addresses. You’ve noticed that some addresses include leading and trailing spaces, as well as uppercase letters, and you want to fix this. More important, you’ve noticed that there’s a duplicate email address.

You decide to clean this up with a comprehension:

Python
>>> emails = {
...     " alice@example.org ",
...     "BOB@example.com",
...     "charlie@EXAMPLE.com",
...     "David@example.net",
...     " bob@example.com",
...     "JohnDoe@example.com",
... }

>>> {email.strip().lower() for email in emails}
{
    'alice@example.org',
    'bob@example.com',
    'johndoe@example.com',
    'charlie@example.com',
    'david@example.net'
}

In the highlighted line, you have a set comprehension that removes leading and trailing spaces from each address using the .strip() method. Then, it applies lowercase to all addresses using .lower(). As a result of the cleanup, the duplicate address is eliminated because sets can only contain unique items.

Filtering Items From Sets

Sometimes, you need to filter an existing set and create a new one with elements that meet a given requirement or condition. For example, say that you want to filter your email addresses set to extract only the .com emails. To do this, you can use the following comprehension:

Python
>>> emails_set = {
...     "alice@example.org",
...     "bob@example.com",
...     "johndoe@example.com",
...     "charlie@example.com",
...     "david@example.net",
... }

>>> {email for email in emails_set if email.endswith(".com")}
{'bob@example.com', 'charlie@example.com', 'johndoe@example.com'}

In this example, you use a conditional to create a set that only includes the email addresses on the .com domain.

Deciding When to Use Set Comprehensions

When deciding whether to use a set comprehension instead of a regular loop or a combination of function calls, you should consider the following factors:

  • Conciseness: Set comprehensions reduce the amount of code compared to equivalent for loops.
  • Readability: Set comprehensions can make your code more explicit and readable.

In practice, you can use set comprehensions when you need to perform the following operations:

  • Create sets from existing iterables by applying data transformations
  • Transform the elements of an existing set
  • Filter the elements of an existing set

So far, you’ve learned how to do all these operations using set comprehensions. Still, you may find other good use cases for set comprehensions during your Python coding experience.

Additionally, there are situations where using set comprehensions may not be necessary. For example, if you need to remove duplicate items from an iterable, then you can simply use the following syntax:

Python
>>> set([2, 2, 1, 4, 2, 3])
{1, 2, 3, 4}

If you don’t need to transform the input data to generate the set elements, then you can just use the set() constructor. This is a great way to remove duplicate items from an iterable. However, it’s important to note that the objects in the input iterable must be hashable, and the original order of the elements will not be preserved.

Exploring Common Bad Practices

There are a few bad practices you’ll want to avoid when working with set comprehensions in your Python code. Some of the most common ones include:

  • Using complex expressions in comprehensions
  • Writing nested comprehensions with several for clauses or conditionals
  • Trying to access comprehension variables from the outside
  • Running costly transformations when building the set elements

Sometimes, you may have a set comprehension where the comprehension expression is too complicated.

For example, say you’ve created a set from a list of numbers. If the number is even, then you want its square. Otherwise, you want its cube. To do this, you can use the following comprehension:

Python
>>> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> {number**2 if number % 2 == 0 else number**3 for number in numbers}
{64, 1, 4, 36, 100, 16, 343, 729, 27, 125}

In this comprehension, you use a relatively complex expression to generate the set elements. It may be challenging to read this comprehension and decipher what it does. When a complicated expression makes your code difficult to read, you may benefit from using a regular for loop instead:

Python
>>> result_set = set()

>>> for number in numbers:
...     if number % 2 == 0:
...         value = number**2
...     else:
...         value = number**3
...     result_set.add(value)
...

>>> result_set
{64, 1, 4, 36, 100, 16, 343, 729, 27, 125}

This loop produces the same result as the comprehension but can be more explicit, making your code more readable.

Nested comprehensions with several for clauses or conditionals can make your code less readable. So, you should generally avoid them and use more readable constructs like a regular loop.

Trying to use the variables that you define in a comprehension outside of the comprehension itself isn’t possible:

Python
>>> {number**3 for number in range(1, 11)}
{64, 1, 512, 8, 1000, 343, 216, 729, 27, 125}

>>> number
Traceback (most recent call last):
    ...
NameError: name 'number' is not defined

The number variable is only visible within the comprehension. If you try to use it outside the comprehension, then you get a NameError exception.

Sometimes, when working with set comprehensions, you may need to run costly data transformations to generate set elements. In these situations, you should be aware that building the final set may take considerable time. A possible workaround is to use a generator that produces the elements on demand.

Conclusion

You’ve learned about Python set comprehensions in detail. They’re a powerful tool for creating, transforming, and filtering sets using concise and clean syntax. You’ve also learned about some bad practices you should avoid when working with set comprehensions.

Set comprehensions are an excellent tool for Python developers. They provide a Pythonic and streamlined way to manipulate sets in Python.

In this tutorial, you’ve:

  • Created new sets with a concise syntax
  • Transformed existing sets with comprehensions
  • Filtered unwanted elements from existing sets
  • Decided when to use set comprehensions in your code

With these skills, you can write more readable and Pythonic code to process sets. As you continue to use set comprehensions, you’ll find them to be an invaluable tool.

Frequently Asked Questions

Now that you have some experience with set comprehensions 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:

Set comprehension is a concise way to create sets in Python using a syntax similar to list comprehension. The primary difference is that a set comprehension uses curly braces {}, while a list comprehension uses square brackets []. The result is a set, which is an unordered collection of unique elements.

You can create a set from an iterable by using the set comprehension syntax: {expression for member in iterable}. This will evaluate the expression for each member of the iterable and add the result to the set, ensuring all elements are unique.

You should consider using set comprehensions over regular loops when you want to create sets concisely and improve code readability. They’re especially useful when transforming or filtering data from an iterable to generate unique set elements.

Common bad practices include using overly complex expressions within comprehensions, writing nested comprehensions with multiple for clauses or conditionals, attempting to access comprehension variables outside the comprehension, and performing costly transformations that could degrade performance.

Yes, you can use set comprehensions to filter elements by adding a conditional at the end of the comprehension: {expression for member in iterable if condition}. This will include only those elements for which the condition evaluates to True.

Take the Quiz: Test your knowledge with our interactive “Python Set Comprehensions: How and When to Use Them” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python Set Comprehensions: How and When to Use Them

In this quiz, you'll test your understanding of Python set comprehensions. Set comprehensions are a concise and quick way to create, transform, and filter sets in Python. They can significantly enhance your code's conciseness and readability compared to using regular for loops to process your sets.

🐍 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 Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

» More about Leodanis

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!