How to copy a set in Python

Learn how to copy a set in Python. Explore different methods, tips, real-world applications, and common error debugging.

How to copy a set in Python
Published on: 
Mon
Apr 6, 2026
Updated on: 
Wed
Apr 8, 2026
The Replit Team

You often need to copy a Python set for data manipulation. This action creates a duplicate without alteration to the original, which is crucial for data integrity and algorithm design.

In this article, you'll explore various techniques, from the copy() method to the set() constructor. We'll also cover practical tips, real-world applications, and advice to debug your code.

Using the set() constructor

original_set = {1, 2, 3, 4, 5}
new_set = set(original_set)
print("Original set:", original_set)
print("Copied set:", new_set)--OUTPUT--Original set: {1, 2, 3, 4, 5}
Copied set: {1, 2, 3, 4, 5}

Using the set() constructor is a straightforward way to create a shallow copy. It works by iterating over the provided set, original_set, and building a new set object from its elements. This process ensures a few key things:

  • The new set, new_set, is a completely separate object in memory.
  • Modifications to the copied set won't affect the original data.

This makes it a safe and Pythonic choice for when you need a duplicate set for further manipulation.

Common methods for copying sets

While the set() constructor is a reliable option, Python also offers the dedicated .copy() method and clever uses of operators like | and *.

Using the .copy() method

original_set = {1, 2, 3, 4, 5}
copied_set = original_set.copy()
original_set.add(6) # Modify original
print("Original:", original_set)
print("Copy:", copied_set)--OUTPUT--Original: {1, 2, 3, 4, 5, 6}
Copy: {1, 2, 3, 4, 5}

The .copy() method offers an explicit and readable way to duplicate a set. As the code demonstrates, when you modify the original_set after copying, the copied_set remains unchanged. This confirms they are two independent objects.

  • This method creates a shallow copy, similar to the set() constructor.
  • Its main advantage is readability. Your code clearly states its intent to create a copy.

Using the | operator (set union)

original_set = {1, 2, 3, 4, 5}
copied_set = original_set | set() # Union with empty set
original_set.clear() # Empty the original
print("Original:", original_set)
print("Copy:", copied_set)--OUTPUT--Original: set()
Copy: {1, 2, 3, 4, 5}

The pipe operator, |, is Python's symbol for a set union. When you perform a union between your original_set and an empty set, set(), you're telling Python to create a new set containing all elements from the original. It's a clever, concise way to get a copy.

  • This operation always returns a new set object, ensuring the copy is independent.

The example confirms this; after clearing the original, the copy remains intact, proving they are separate objects in memory.

Using the unpacking operator *

original_set = {1, 2, 3, 4, 5}
copied_set = {*original_set}
original_set.remove(5)
print("Original:", original_set)
print("Copy:", copied_set)--OUTPUT--Original: {1, 2, 3, 4}
Copy: {1, 2, 3, 4, 5}

The unpacking operator, *, offers a modern and concise syntax for copying a set. When you use the expression {*original_set}, you're telling Python to take all the elements from the original set and place them into a new one. This creates an independent shallow copy.

  • This method is often favored for its elegance and readability.
  • It's a visually clean approach that's popular in contemporary Python code.

Advanced techniques for set manipulation

When your needs go beyond a simple shallow copy, Python provides advanced tools like the copy module, type conversion, and comprehensions for more control.

Using the copy module

import copy
original_set = {1, 2, 3, 4, 5}
shallow_copy = copy.copy(original_set)
deep_copy = copy.deepcopy(original_set)
print("Original:", original_set)
print("Shallow copy:", shallow_copy)
print("Deep copy:", deep_copy)--OUTPUT--Original: {1, 2, 3, 4, 5}
Shallow copy: {1, 2, 3, 4, 5}
Deep copy: {1, 2, 3, 4, 5}

Python's built-in copy module gives you explicit control over duplication. It offers functions for both shallow and deep copying, which is especially useful when dealing with complex, nested data structures.

  • The copy.copy() function creates a shallow copy, behaving just like the .copy() method.
  • The copy.deepcopy() function creates a deep copy. This is crucial when a set contains mutable objects, like other sets or lists, as it recursively copies everything. For a simple set of numbers, its result is identical to a shallow copy.

Type conversion technique

original_set = {1, 2, 3, 4, 5}
# Convert to list and back to set
list_copy = list(original_set)
set_copy = set(list_copy)
print("Original:", original_set)
print("Via list conversion:", set_copy)--OUTPUT--Original: {1, 2, 3, 4, 5}
Via list conversion: {1, 2, 3, 4, 5}

You can also copy a set by converting it to another data type, like a list, and then immediately converting it back. This two-step process works because both the list() and set() constructors create new objects in memory. The final result is a completely new set, independent of the original.

  • This technique is more indirect than using .copy() or the set() constructor directly.
  • It effectively creates a shallow copy by leveraging Python's type-casting behavior, ensuring the new set is a separate object.

Creating filtered copies with comprehensions

original_set = {1, 2, 3, 4, 5, 6}
even_numbers = {x for x in original_set if x % 2 == 0}
doubled_values = {x * 2 for x in original_set}
print("Original:", original_set)
print("Even numbers:", even_numbers)
print("Doubled values:", doubled_values)--OUTPUT--Original: {1, 2, 3, 4, 5, 6}
Even numbers: {2, 4, 6}
Doubled values: {2, 4, 6, 8, 10, 12}

Set comprehensions offer a concise way to create a new set based on an existing one. This technique lets you iterate over the original set and apply custom logic to each element, generating a modified copy all in one line.

  • You can filter elements, like creating the even_numbers set by including only items that satisfy a condition like if x % 2 == 0.
  • You can also transform elements, such as creating doubled_values by applying an operation like x * 2 to every item.

Move faster with Replit

Replit is an AI-powered development platform that comes with all Python dependencies pre-installed, so you can skip setup and start coding instantly. Instead of just piecing together techniques like .copy(), you can use Agent 4 to build a complete application from a simple description. You could ask it to create:

  • A duplicate email remover that processes a list of contacts and returns a clean set of unique addresses.
  • A user permission tool that combines a base set of permissions with a new set to grant specific access levels.
  • A content moderation utility that filters a set of raw user comments, creating a new, clean set by removing forbidden words.

Simply describe your app, and Replit will write the code, test it, and fix issues automatically, all within your browser.

Common errors and challenges

When copying sets, you might run into a few common pitfalls that can introduce subtle bugs into your code.

  • Mistakenly modifying a set during iteration. It’s a classic mistake to try adding or removing elements from a set while looping over it. Python raises a RuntimeError because changing the set’s size during iteration can cause unpredictable behavior. The solution is to iterate over a copy of the set while making changes to the original.
  • Trying to use mutable objects as set elements. Set elements must be hashable, meaning their value cannot change after they're created. This is why you can add numbers, strings, and tuples, but not mutable objects like lists or other sets. If you try, Python will throw a TypeError. The fix is to convert any mutable collections to an immutable type, like a tuple, before adding them.
  • Misunderstanding the == vs. is operators. It's crucial to know the difference between these two. The == operator checks for value equality—do two sets contain the same elements? In contrast, the is operator checks for identity—do two variables point to the exact same object in memory? A new copy will be == to the original, but it will not be is the original, and confusing them can lead to bugs.

Mistakenly modifying a set during iteration

It’s tempting to remove elements from a set while looping over it, but this is a classic mistake. Changing a set's size during iteration confuses Python, causing it to raise a RuntimeError. The following code demonstrates this exact problem.

numbers = {1, 2, 3, 4, 5, 6, 7, 8}
for num in numbers:
if num % 2 == 0:
numbers.remove(num)
print(numbers)

This code triggers a RuntimeError because the for loop's iterator becomes invalid. When numbers.remove(num) changes the set's size mid-iteration, Python can no longer track its position. The correct approach is shown next.

numbers = {1, 2, 3, 4, 5, 6, 7, 8}
numbers_to_remove = {num for num in numbers if num % 2 == 0}
numbers -= numbers_to_remove
print(numbers)

The correct approach separates identification from removal. First, a set comprehension creates a new set, numbers_to_remove, holding all the even numbers. Only after this loop completes does the code modify the original set using the difference update operator, -=. This two-step pattern prevents the RuntimeError by ensuring the set you're iterating over isn't changed mid-loop. It's a key technique for safe filtering.

Trying to use mutable objects as set elements

A core rule of Python sets is that their elements must be immutable, or "hashable." This means you can't add objects that can change, like a list. Attempting to do so disrupts the set's internal structure, causing a TypeError. The code below shows what happens.

user_preferences = set()
favorite_colors = ["blue", "green", "red"]
user_preferences.add(favorite_colors)
print(user_preferences)

This code fails because the add() method attempts to insert favorite_colors, which is a list. Since lists are mutable, Python rejects them. The fix involves ensuring the item you add is unchangeable, as shown in the code below.

user_preferences = set()
favorite_colors = ["blue", "green", "red"]
user_preferences.add(tuple(favorite_colors))
print(user_preferences)

The fix is to convert the list to an immutable type before adding it. By wrapping favorite_colors in the tuple() constructor, you create a hashable version that the set can accept. This is a common workaround for the TypeError.

  • You'll often encounter this when working with sets that need to contain other collections, like lists of coordinates or groups of tags.

Misunderstanding the == vs. is operators with sets

It's a common mix-up to use the is operator when you really mean ==. One checks for object identity, while the other checks for value equality. This subtle difference can cause unexpected behavior, as the following code demonstrates.

set1 = {1, 2, 3}
set2 = {1, 2, 3}
if set1 is set2:
print("Sets have the same identity")
else:
print("Sets are different objects")
print(f"But they have the same elements: {set1 == set2}")

The code prints “Sets are different objects” because the is operator checks if two variables point to the same memory location. Since set1 and set2 are created separately, they aren't identical. Now, see how to properly assign a reference.

set1 = {1, 2, 3}
set2 = set1.copy() # Create a proper copy
set3 = set1 # Create a reference

set1.add(4)
print("Set1:", set1)
print("Set2 (proper copy):", set2)
print("Set3 (reference):", set3)

This code highlights a critical distinction. set2 is a true copy created with .copy(), so it's unaffected when set1 changes. In contrast, set3 is just a reference—another name for set1. Because they point to the same object, modifying set1 also changes set3. This is a common source of bugs, especially when passing sets to functions, as you might unintentionally alter data you thought was a separate copy.

Real-world applications

Beyond avoiding errors, copying sets is key for preserving data and comparing collections with operators like &, -, and |.

Preserving original data with the .copy() method

The .copy() method is crucial when you need to modify a set for analysis while ensuring the original data remains untouched for reference or comparison.

text = "To be or not to be, that is the question."
words = text.lower().replace(',', '').replace('.', '').split()
unique_words = set(words)
# Create a copy to work with while preserving original
analysis_set = unique_words.copy()
analysis_set.remove('the') # Remove common words for analysis

print(f"Original unique words: {unique_words}")
print(f"Analysis set (without common words): {analysis_set}")

This example shows how copying is essential for data processing. The code first tokenizes a sentence, creating a set of unique_words. Then, it makes a duplicate called analysis_set using the .copy() method.

  • This creates an independent copy, so you can modify it freely.
  • Removing the word 'the' from analysis_set doesn't affect the original unique_words set.

This technique is perfect for when you need to filter or alter data for a specific task while keeping the original dataset intact for other purposes.

Comparing collections with &, -, and | operators

These operators let you compare collections concisely, finding the intersection (&), difference (-), or union (|) between two sets with a single expression.

user1_cart = {"apple", "banana", "orange", "pineapple", "mango"}
user2_cart = {"apple", "orange", "grape", "watermelon", "kiwi"}

print(f"User 1's cart: {user1_cart}")
print(f"User 2's cart: {user2_cart}")
print(f"Items in both carts: {user1_cart & user2_cart}")
print(f"Items only in User 1's cart: {user1_cart - user2_cart}")
print(f"Items only in User 2's cart: {user2_cart - user1_cart}")

This code uses a practical e-commerce example to show set operators in action. By treating each shopping cart as a set, you can perform powerful comparisons with minimal code.

  • The expression user1_cart & user2_cart efficiently finds all items that appear in both collections.
  • Similarly, user1_cart - user2_cart isolates the items exclusive to the first user's cart.

This approach is far more concise and often faster than writing manual loops to achieve the same result, making it a go-to for data comparison tasks.

Get started with Replit

Put your knowledge into practice and build a real tool. Just tell Replit Agent: "Create a script to find common followers between two social media accounts" or "Build a duplicate email remover for a contact list".

Replit Agent will write the code, test for errors, and deploy your application for you. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.