discard and remove
s.discard(x) takes x out of the set s. If x is not in the set, nothing happens. Python also has s.remove(x), which works the same when x is there. When it is not, remove stops the program with a KeyError.
found = set(["cat", "tree", "sun"])
found.discard("sun")
found.discard("zzz")
print(len(found))
found.remove("zzz")
2
Traceback (most recent call last):
...
KeyError: 'zzz'
Use discard whenever you are not sure the value is in the set. Use remove only when a missing value would be a bug that you want to hear about.
Looping over a set
for x in s visits each value of the set once. The order is not fixed: it can differ from the order you added the values in, and from one run to the next. So a set loop suits jobs where order does not matter, such as a total, a count or a check.
Do not remove values from a set while looping over it. Python stops with RuntimeError: Set changed size during iteration. Remove first, then loop, or build a second collection of the values to keep.
The exercise, step by step
A word game keeps the words a player found in the set found. The words "qqq" and "zzz" are not allowed. The task is to remove both, then score one point per letter over the words that are left. The starter code prints how many words remain and the score.
- Call
found.discard("qqq")andfound.discard("zzz"). The player never found"zzz", so the second call changes nothing and raises no error. Withremovethat line would crash. - Below
score = 0, writefor word in found:. - Inside the loop, add
len(word)toscore.
words = ["cat", "tree", "sun", "qqq", "moon"]
found = set(words)
found.discard("qqq")
found.discard("zzz")
print(len(found), "words")
score = 0
for word in found:
score += len(word)
print(score, "points")
4 words
14 points
The four words left are cat, tree, sun and moon, and 3 + 4 + 3 + 4 = 14. Whatever order the loop visits them in, the total is the same.
Choosing between them
The two methods differ only for a missing value. A game that takes banned words out of whatever the player found should not crash when the banned word was never found, so discard fits. If your program is sure that a value is in the set, remove turns a wrong assumption into an immediate error with the missing value in the message, instead of letting the mistake pass unnoticed. In this exercise the second banned word is absent by design, which is why the lesson uses discard for both calls, so the two lines look alike.
Common mistakes
- Using
remove("zzz")for a word that may be absent. - Expecting the loop to print words in the order of the list. A set does not keep it.
- Calling
discardinside the scoring loop on the set being looped over.
Key takeaways
discard(x)is safe whenxmay be missing;remove(x)raisesKeyError.- A set loop visits every value once, in no fixed order.
- Do not change the size of a set during its own loop.
