Skip to content

Commit 6bb855b

Browse files
committed
working on dicts.md
1 parent ca74b5b commit 6bb855b

File tree

1 file changed

+131
-26
lines changed

1 file changed

+131
-26
lines changed

dicts.md

Lines changed: 131 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
# Dictionaries
22

3-
**TODO:** write the lists-and-tuples.md this tutorial links to.
4-
53
Now we know how [lists and tuples](lists-and-tuples.md) work and how
6-
to [for loop](loops.md#for-loops) over them. We also did an exercise
7-
with code like this:
4+
to [for loop](loops.md#for-loops) over them. If we make some kind of
5+
program that needs to keep track of people's usernames and passwords,
6+
we can use a list for that:
87

98
```py
109
userlist = [
@@ -13,14 +12,14 @@ userlist = [
1312
]
1413
```
1514

16-
Then to check if a username and password were correct we did
17-
`(username, password) in userlist`. Adding new users was also easy as
18-
appending to that list.
15+
Then to check if a username and password are correct we can do
16+
`(username, password) in userlist`. Or we can add a new user easily by
17+
appending a new `(username, password)` tuple to the userlist.
1918

20-
What if we need to check if a username is in the users, but we don't
21-
need to know the password? `username in userlist` is always False
22-
because the user list consists of (username,password) pairs, so we need
23-
to for loop over the whole list:
19+
But what if we need to check if a username exists, but we don't know
20+
the password? `username in userlist` is always False because the user
21+
list consists of `(username, password)` pairs instead of just
22+
usernames, so we need to for loop over the whole userlist:
2423

2524
```py
2625
username_exists = False
@@ -32,23 +31,24 @@ if username_exists:
3231
# do something
3332
```
3433

35-
Getting a user's password also requires a similar loop:
34+
Or how about getting a user's password if we know the username? This
35+
also requires going through the whole list.
3636

3737
```py
3838
password = None
3939
for user in userlist:
4040
if user[0] == username:
4141
password = user[1]
4242
break
43-
# make sure password isn't still None and do something with it
43+
# make sure password is not None and do something with it
4444
```
4545

46-
This works just fine because our user list only contains two users, but
47-
it would be slow if the userlist was bigger.
46+
As you can see, a list of `(username, password)` pairs is not an ideal
47+
way to store our usernames and passwords.
4848

4949
## What are dictionaries?
5050

51-
A better way to store user information might be a dictionary.
51+
A better way to store user information might be a dictionary:
5252

5353
```py
5454
passwords = {
@@ -64,8 +64,8 @@ values so I named the variable `passwords`.
6464

6565
There are a few big differences between dictionaries and lists of pairs:
6666

67-
- Dictionaries are not ordered. There's **no guarantees** about which
68-
order the username:password pairs appear in when we do something
67+
- Dictionaries are not ordered. There are **no guarantees** about which
68+
order the `username: password` pairs appear in when we do something
6969
with the dictionary.
7070
- Checking if a key is in the dictionary is simple and fast. We don't
7171
need to for loop through the whole dictionary.
@@ -93,7 +93,10 @@ variable names and values are what our variables point to.
9393
```
9494

9595
So if you have trouble remembering how dictionaries work just compare
96-
them to variables.
96+
them to variables. A dictionary is a perfect way to store our usernames
97+
and passwords. We don't care about which order the users were added in,
98+
it's impossible to add multiple users with the same username and
99+
getting a user's password is easy.
97100

98101
## What can we do with dictionaries?
99102

@@ -108,28 +111,36 @@ lists and dictionaries have a length.
108111
>>>
109112
```
110113

111-
We can get a value of a key with `the_dict[key]`. Trying to get the
112-
value of a non-existing key gives us an error. We can also add new
113-
key:value pairs by doing `the_dict[key] = value`.
114+
We can get a value of a key with `the_dict[key]`. This is a lot easier
115+
and faster than for-looping over a list of pairs.
114116

115117
```py
116118
>>> passwords['me']
117119
'my password'
118120
>>> passwords['you']
119121
'your password'
122+
>>>
123+
```
124+
125+
Trying to get the value of a non-existing key gives us an error, but we
126+
can add new `key: value` pairs by doing `the_dict[key] = value`.
127+
128+
```py
120129
>>> passwords['lol']
121130
Traceback (most recent call last):
122131
File "<stdin>", line 1, in <module>
123132
KeyError: 'lol'
124133
>>> passwords["lol"] = "lol's password"
134+
>>> passwords["lol"]
135+
"lol's password"
125136
>>> passwords
126137
{'lol': "lol's password", 'you': 'your password', 'me': 'my password'}
127138
>>>
128139
```
129140

130-
For looping over a dictionary gets its keys, and checking if something's
131-
in the dictionary checks if the dictionary has a key like that. This can
132-
be confusing at first but you'll get used to this.
141+
For looping over a dictionary gets its keys, and checking if something
142+
is in the dictionary checks if the dictionary has a key like that. This
143+
can be confusing at first but you'll get used to this.
133144

134145
```py
135146
>>> 'me' in passwords
@@ -190,7 +201,101 @@ me: my password
190201
>>>
191202
```
192203

193-
**TODO:** lists as keys vs tuples as keys.
204+
This is also useful for checking if the dictionary has a `key: value`
205+
pair.
206+
207+
```py
208+
>>> ('me', 'my password') in passwords.items() # correct username and password
209+
True
210+
>>> ('me', 'whatever') in passwords.items() # wrong username or password
211+
False
212+
>>>
213+
```
214+
215+
## Limitations
216+
217+
Sometimes it might be handy to use lists as dictionary keys, but it
218+
just doesn't work. I'm not going to explain why Python doesn't allow
219+
this because usually we don't need to worry about that.
220+
221+
```py
222+
>>> stuff = {['a', 'b']: 'c', ['d', 'e']: 'f'}
223+
Traceback (most recent call last):
224+
File "<stdin>", line 1, in <module>
225+
TypeError: unhashable type: 'list'
226+
>>>
227+
```
228+
229+
On the other hand, tuples work just fine:
230+
231+
```py
232+
>>> stuff = {('a', 'b'): 'c', ('d', 'e'): 'f'}
233+
>>> stuff
234+
{('a', 'b'): 'c', ('d', 'e'): 'f'}
235+
>>>
236+
```
237+
238+
The values of a dictionary can be anything.
239+
240+
```py
241+
>>> stuff = {'a': [1, 2, 3], 'b': [4, 5, 6]}
242+
>>> stuff
243+
{'a': [1, 2, 3], 'b': [4, 5, 6]}
244+
>>>
245+
```
246+
247+
## Summary
248+
249+
- Dictionaries consist of `key: value` pairs.
250+
- Variables are stored in a dictionary with their names as keys, so
251+
dictionaries behave a lot like variables:
252+
- Dictionaries are not ordered.
253+
- Setting or getting the value of a key is simple and fast.
254+
- Dictionaries can't contain the same key more than once.
255+
- For-looping over a dictionary loops over its keys, and checking if
256+
something is in the dictionary checks if the dictionary has a key
257+
like that. The `values()` and `items()` methods return things that
258+
behave like lists of values or `(key, value)` pairs instead.
259+
260+
## Examples
261+
262+
This program counts how many times words appear in a sentence.
263+
`sentence.split()` creates a list of words in the sentence, see
264+
`help(str.split)` for more info.
265+
266+
```py
267+
sentence = input("Enter a sentence: ")
268+
269+
counts = {} # {word: count, ...}
270+
for word in sentence.split():
271+
if word in counts:
272+
# we have seen this word before
273+
counts[word] += 1
274+
else:
275+
# this is the first time this word occurs
276+
counts[word] = 1
277+
278+
print() # display an empty line
279+
for word, count in counts.items():
280+
if count == 1:
281+
# "1 times" looks weird
282+
print(word, "appears once in the sentence")
283+
else:
284+
print(word, "appears", count, "times in the sentence")
285+
```
286+
287+
Running the program might look like this:
288+
289+
Enter a sentence: this is a test and this is quite long because this is a test
290+
291+
is appears 3 times in the sentence
292+
long appears once in the sentence
293+
a appears 2 times in the sentence
294+
because appears once in the sentence
295+
this appears 3 times in the sentence
296+
quite appears once in the sentence
297+
and appears once in the sentence
298+
test appears 2 times in the sentence
194299

195300
***
196301

0 commit comments

Comments
 (0)