Dictionaries and the .get() Method
If the word is not a key, the method returns the default value 0.
Try it: Counting Words with a Dictionary
The py4e histogram pattern: split each line into words, count them with counts[word] = counts.get(word, 0) + 1, then find the most common word with a max loop or by sorting (count, word) tuples in reverse.
How it works
- Optionally remove punctuation with str.translate and lower-case the line, then split() it into words.
- For each word: counts.get(word, 0) returns the current count or 0 for a new word; store it plus one (or the if word not in counts form).
- A dict remembers insertion order: a word's position is fixed the first time it is seen.
- Max loop: keep the word whose count is strictly larger than the best so far (the first word wins a tie).
- Or build [(count, word) …], sort with reverse=True (ties ordered by the word, reversed) and slice [:N].
Default run (25 steps): Start with an empty dict. The text has 3 lines. … [:3] keeps the top 3: [(5, 'the'), (2, 'sat'), (2, 'on')].
Simplified: Printable-ASCII text up to 320 characters, 8 lines and 60 words, typed in the lab instead of read from a file or URL.
Loading the simulation…
From Web Text to Word Counts
Imagine downloading a text file from the internet and needing to find which words appear most often. Counting manually would be tedious and error-prone. A program can instead retrieve the text, read it line by line, split each line into words, and keep a running total in a dictionary.
This task has two connected parts. First, urllib.request.urlopen() opens a web URL and returns a file-like object. Second, a dictionary records how many times each word occurs. The remote location does not change the basic parsing approach: after the URL is opened, the data can be processed line by line in the same general way as file data.
A First Dictionary Trace
A dictionary is a key-value store. In a word-frequency dictionary, each unique word is a key and its total occurrence count is the value. The dictionary starts empty. Each processed word either creates a new key with count 1 or increases the value already stored for that key.
Counting Two Short Lines
Trace the dictionary while processing the source example lines: But soft what and light through yonder.
- 1Start
The counts dictionary is empty: {}.
- 2Process But
But is not present, so its count becomes 1.
- 3Process soft
soft is new, so its count becomes 1.
- 4Process what
what is new, so its count becomes 1.
- 5Process light
light is new, so its count becomes 1.
- 6Process through
through is new, so its count becomes 1.
- 7Process yonder
yonder is new, so its count becomes 1.
The final dictionary contains each of the six words with a value of 1.
Reading and Updating Counts
Each line supplied by the web source arrives as bytes. Bytes must be decoded into a string before the line can be split into words. The processing sequence is therefore: obtain a line, decode it, split it into words, then process each word.
The expression reads the current count with get. If the word is already a key, counts.get(word, 0) returns its current value. If the word is not a key, the method returns the default value 0. Adding 1 then produces the correct next count in either case, and assigning the result back to counts[word] stores it.
| Word status | Value returned by get | Value stored after adding 1 |
|---|---|---|
| Word is already in the dictionary | The current count | The current count increased by 1 |
| Word is not in the dictionary | 0 | 1 |
The two cases handled by dictionary.get(word, 0).
Tracing Repeated Words
The important state change appears when a word repeats. A first occurrence creates a key with value 1. A later occurrence does not create a separate entry; it reads the existing value and replaces it with that value plus 1.
Following One Repeated Word
Trace the count for the word soft while processing the generated sequence: soft, light, soft.
- 1Read soft first time
soft is absent, so get returns 0. Adding 1 stores soft with count 1.
- 2Read light
light is absent, so light receives count 1. The existing soft count remains 1.
- 3Read soft second time
soft is present with count 1. get returns 1, adding 1 produces 2, and soft is stored with count 2.
The final counts assign soft the value 2 and light the value 1.
counts = {}
counts[word] = counts.get(word, 0) + 1- 1Before the update, counts contains the results of all earlier words.
- 2The lookup uses the current word as the key.
- 3The assignment updates only that word's value while preserving the other dictionary entries.
- Create an empty dictionary for the accumulated counts.
- Read the current count or use 0, add 1, and store the result under the word.
Debugging the Loop
When the result looks wrong, inspect the program while it runs instead of looking only at the final dictionary. Print the word being processed and the dictionary after each update. This exposes whether the input is being decoded correctly, whether the loops are iterating as expected, and whether counts are accumulating.
Mistakes in Frequency Updates
Common mistake Resetting a word to 1 every time it appears
What it looks likecounts[word] = 1Why it failsA repeated word loses its previous count, so the dictionary cannot accumulate the total number of occurrences.
Do this insteadRead the existing value or use 0, then add 1 with counts[word] = counts.get(word, 0) + 1.
Common mistake Forgetting to store the updated value
What it looks likecounts.get(word, 0) + 1Why it failsThe expression calculates a number but does not assign that number back to the dictionary key.
Do this insteadAssign the result to counts[word].
Common mistake Processing bytes as though they were already readable text
What it looks likeSplitting a web line before decoding it
Why it failsEach line from the web source arrives as bytes and must be decoded to a string before it can be split into words.
Do this insteadDecode each line first, then split the resulting string.
Common mistake Inspecting only the final dictionary
What it looks likePrinting counts only after both loops finish
Why it failsThe final state does not show when an unexpected word or incorrect count entered the result.
Do this insteadPrint the current word and dictionary inside the processing loop to trace state changes.
A word is processed three times. Describe the dictionary value after the first, second, and third occurrences when the update is counts[word] = counts.get(word, 0) + 1. Then explain what would happen if the update were replaced by counts[word] = 1.
Hints
- For the first occurrence, the word is absent and get returns 0.
- For later occurrences, get returns the value already stored for the word.
- Compare accumulating the old value plus 1 with replacing the value by 1.
A Reliable Processing Pattern
- 1Open the remote URL with
urllib.request.urlopen(). - 2Iterate over the returned file-like object one line at a time.
- 3Decode each bytes line into a string.
- 4Split the decoded string into individual words.
- 5For each word, use counts[word] =
counts.get(word, 0)+ 1. - 6Inspect the word and dictionary during debugging when the final counts are unexpected.
Suppose the next three processed words are soft, soft, and what. Write the dictionary state after each update, starting with an empty dictionary. In a second attempt, describe which stage you would inspect first if an unexpected bytes value appeared as a word.
Hints
- The first soft creates a key with value 1.
- The second soft increases that value.
- what is a separate key.
- An unexpected bytes value points you toward the decoding stage.
Key Takeaways
- 1
urllib.request.urlopen()returns a file-like object that can be iterated line by line. - 2Web lines arrive as bytes, so they must be decoded into strings before word processing.
- 3A word-frequency dictionary maps each unique word to its total occurrence count.
- 4
counts.get(word, 0)handles both a word's first occurrence and its later occurrences. - 5Printing the current word and dictionary during the loop reveals decoding, iteration, and update errors.
At a glance
- Remote text can be opened as a file-like object and processed one line at a time.
- Each bytes line must be decoded before it is split into words.
- The dictionary stores words as keys and total frequencies as values.
- The expression counts[word] =
counts.get(word, 0)+ 1 accumulates counts correctly for new and repeated words. - Tracing each word and dictionary state is an effective way to find word-counting mistakes.