8.2.7. Set Methods#
Python sets have methods for adding, removing, and checking elements.
Method |
Description |
|---|---|
|
Adds a single element |
|
Adds multiple elements |
|
Returns a shallow copy of the set |
|
Removes element, raises |
|
Removes element, silent if missing |
|
Removes and returns an arbitrary element |
|
Empties the set |
|
Returns |
|
Returns |
|
Returns |
import sys
from pathlib import Path
# Find project root by looking for _config.yml
current = Path.cwd()
for parent in [current, *current.parents]:
if (parent / '_config.yml').exists():
project_root = parent
break
else:
project_root = Path.cwd().parent.parent
# Add project root to path
sys.path.insert(0, str(project_root))
# Import shared teaching helpers and cell magics
from shared import thinkpython, diagram, jupyturtle, structshape
from shared.download import download
8.2.7.1. Adding elements:#
add()update(): adds multiple elements, similar todict.update().
s = {1, 2, 3}
s.add(4) # {1, 2, 3, 4}
s.update([5, 6]) # {1, 2, 3, 4, 5, 6}
s
{1, 2, 3, 4, 5, 6}
8.2.7.2. Copy vs aliasing#
Sets are mutable, so assignment shares the same object. Use .copy() when you need an independent set.
a = {1, 2}
b = a # alias (same object)
c = a.copy() # separate object
a.add(3)
print("a:", a)
print("b:", b)
print("c:", c)
a: {1, 2, 3}
b: {1, 2, 3}
c: {1, 2}
8.2.7.3. Removing elements:#
remove()discard()pop()clear()
s = {1, 2, 3}
s.remove(3) # raises KeyError if not found
print(s) # {1, 2}
s.discard(3) # silent if not found — safer
print(s) # {1, 2}
s.pop() # removes and returns an arbitrary element
print(s) # which item is removed is arbitrary
s.clear() # empties the set
print(s) # set()
{1, 2}
{1, 2}
{2}
set()
If you use remove() in a for loop for a set, you may run into an error because Python creates an internal iterator that tracks position inside the set. The moment you call s.remove(), the set’s structure changes and the iterator breaks and raises an error.
The solution to this problem is to iterate over a copy or just use a while loop.
%%expect RuntimeError
s = {1, 2, 3,}
for item in s:
s.remove(item)
print(f"Processing {item}")
Processing 1
RuntimeError: Set changed size during iteration
### iterate through copy of the set while modifying the original
for item in s.copy(): # iterate over copy
s.remove(item) # modify original safely
print(f"Processing {item}")
s
Processing 2
Processing 3
set()
# process all items, consuming the set
s = {1, 2, 3}
while s:
item = s.pop()
print(f"Processing {item}")
# s is now empty
Processing 1
Processing 2
Processing 3
s.pop() is useful when you want to process and consume a set one element at a time, and you don’t care which element you get. This behavior is different from pop() in list and dict.
|
|
|
|
|---|---|---|---|
Removes |
by index |
by key |
arbitrary element |
Returns |
removed value |
removed value |
removed value |
Default arg |
index (default |
key + optional default |
none |
If not found |
|
|
|
Predictable? |
yes (by index) |
yes (by key) |
no (arbitrary item) |
8.2.7.4. Checking membership:#
s = {1, 2, 3}
print(3 in s) # True
print(3 not in s) # False
True
False
8.2.7.5. Subset & Superset:#
a = {1, 2}
b = {1, 2, 3}
a.issubset(b) # True — all of a is in b
b.issuperset(a) # True — b contains all of a
a.isdisjoint(b) # False — they share elements
False
Operator equivalents for subset/superset are often used in real code:
a = {1, 2}
b = {1, 2, 3}
print(a < b) # proper subset
print(a <= b) # subset
print(b > a) # proper superset
print(b >= a) # superset
print(a <= a) # True (same set is subset of itself)
print(a < a) # False (not a proper subset)
True
True
True
True
True
False
### Exercise: Update and Membership Check
# 1. Start with fruits = {"apple", "banana"}.
# 2. Add "cherry" and update with ["banana", "mango"].
# 3. Remove "apple" safely.
# 4. Print whether "mango" is in fruits.
# 5. Print whether {"banana", "cherry"} is a subset of fruits.
### Your code starts here.
### Your code ends here.
True
True