Skip to content

Commit f590ca5

Browse files
committed
Add data structure section
1 parent 62fbed3 commit f590ca5

File tree

3 files changed

+244
-0
lines changed

3 files changed

+244
-0
lines changed

source-code/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,5 @@ was used to develop it.
2727
1. `oo_vs_functional.ipynb`: comparing object-oriented approach to
2828
functional approach, including coroutines.
2929
1. `metaclasses`: illustration of the use of metaclasses in Python.
30+
1. `data-structures`: illustration of Python and standard library data
31+
structures.

source-code/data-structures/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Data structures
2+
3+
Python as well as its standard library have many data structures that help you
4+
write elegant and efficient code. Here you will soe examples.
5+
6+
7+
## What is it?
8+
9+
1. `defaultdict.ipynb`: Jupyter notebook that illustrates the use of
10+
`collections.defaultdict` with a default factory for a Python `list` and
11+
a `dataclasss`.
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "2462a390-11a0-4d96-be42-a215460ee554",
6+
"metadata": {},
7+
"source": [
8+
"# Requirements"
9+
]
10+
},
11+
{
12+
"cell_type": "code",
13+
"execution_count": 1,
14+
"id": "4012d44e-1e7f-488d-bb19-d40466a0b800",
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"from collections import defaultdict\n",
19+
"from dataclasses import dataclass"
20+
]
21+
},
22+
{
23+
"cell_type": "markdown",
24+
"id": "62c1100f-d14c-4773-a87d-9b7935d55dcd",
25+
"metadata": {},
26+
"source": [
27+
"# defaultdict"
28+
]
29+
},
30+
{
31+
"cell_type": "markdown",
32+
"id": "771384fa-293a-4f00-94f9-0c5d28f19ed5",
33+
"metadata": {},
34+
"source": [
35+
"The `defaultdict` class is quite convenient since you don't have to test whether a key is already in a dictionary. If it is not, a factory is used to create an initial entry."
36+
]
37+
},
38+
{
39+
"cell_type": "markdown",
40+
"id": "f3951a33-b671-4603-8349-61c1641ae405",
41+
"metadata": {},
42+
"source": [
43+
"## Simple example"
44+
]
45+
},
46+
{
47+
"cell_type": "markdown",
48+
"id": "a2630300-45fd-4d51-8a05-a05bad9ee9d6",
49+
"metadata": {},
50+
"source": [
51+
"Consider a dictionary that has lists as values. If a key is not in the dictionary, it should be initialized with an empty list. The factory function for an empty list is the `list` function."
52+
]
53+
},
54+
{
55+
"cell_type": "code",
56+
"execution_count": 2,
57+
"id": "67799112-3eb0-4410-b260-5c4646adffa6",
58+
"metadata": {
59+
"tags": []
60+
},
61+
"outputs": [],
62+
"source": [
63+
"multiples = defaultdict(list)"
64+
]
65+
},
66+
{
67+
"cell_type": "markdown",
68+
"id": "556ecf15-3003-49f8-aa9b-e9f3998f2855",
69+
"metadata": {},
70+
"source": [
71+
"Now we can add data to the dictionary, for each integer between 0 and 20, we check whether the number is divisible by 2, 3, 4, or 5, and append it to the list that is the value for the divisor (which is the key)."
72+
]
73+
},
74+
{
75+
"cell_type": "code",
76+
"execution_count": 3,
77+
"id": "34147d51-a265-46b8-9e22-10b81460c006",
78+
"metadata": {},
79+
"outputs": [],
80+
"source": [
81+
"for number in range(20):\n",
82+
" for divisor in range(2, 6):\n",
83+
" if number % divisor == 0:\n",
84+
" multiples[divisor].append(number)"
85+
]
86+
},
87+
{
88+
"cell_type": "code",
89+
"execution_count": 4,
90+
"id": "d533abb9-7fcc-4ddf-895b-a13a71af138a",
91+
"metadata": {},
92+
"outputs": [
93+
{
94+
"data": {
95+
"text/plain": [
96+
"defaultdict(list,\n",
97+
" {2: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18],\n",
98+
" 3: [0, 3, 6, 9, 12, 15, 18],\n",
99+
" 4: [0, 4, 8, 12, 16],\n",
100+
" 5: [0, 5, 10, 15]})"
101+
]
102+
},
103+
"execution_count": 4,
104+
"metadata": {},
105+
"output_type": "execute_result"
106+
}
107+
],
108+
"source": [
109+
"multiples"
110+
]
111+
},
112+
{
113+
"cell_type": "markdown",
114+
"id": "4fb29e3d-4264-4030-b933-b101c115d923",
115+
"metadata": {},
116+
"source": [
117+
"## Arbitrary classes"
118+
]
119+
},
120+
{
121+
"cell_type": "markdown",
122+
"id": "667ee4ca-6b2f-4ec0-823e-beef80dbbe93",
123+
"metadata": {},
124+
"source": [
125+
"`defaultdict` also supports arbitrary objects as default values. Consider the following dataclass that represents a person."
126+
]
127+
},
128+
{
129+
"cell_type": "code",
130+
"execution_count": 5,
131+
"id": "0d049fe8-5b12-4c35-a730-1ddb47db55e8",
132+
"metadata": {},
133+
"outputs": [],
134+
"source": [
135+
"@dataclass\n",
136+
"class Person:\n",
137+
" first_name: str = None\n",
138+
" last_name: str = None\n",
139+
" age: int = None"
140+
]
141+
},
142+
{
143+
"cell_type": "markdown",
144+
"id": "928778d2-6fd8-4662-bb31-857e3a87f2c5",
145+
"metadata": {},
146+
"source": [
147+
"The constructor is the default factory in this case."
148+
]
149+
},
150+
{
151+
"cell_type": "code",
152+
"execution_count": 6,
153+
"id": "1eec5ce6-3d7e-4e64-abd1-86f5f92e1446",
154+
"metadata": {},
155+
"outputs": [],
156+
"source": [
157+
"people = defaultdict(Person)"
158+
]
159+
},
160+
{
161+
"cell_type": "markdown",
162+
"id": "aa0d20b2-ef70-487f-8637-cc6060355c1f",
163+
"metadata": {},
164+
"source": [
165+
"When a new person turns up, a default `Person` is constructed with `None` for each attribute, and one of the attributes, `first_name` is assigned to below."
166+
]
167+
},
168+
{
169+
"cell_type": "code",
170+
"execution_count": 7,
171+
"id": "6732bd91-c726-4603-b4c4-7c70fc5eae7d",
172+
"metadata": {},
173+
"outputs": [],
174+
"source": [
175+
"people['gjb'].first_name = 'Geert Jan'"
176+
]
177+
},
178+
{
179+
"cell_type": "markdown",
180+
"id": "63b5c683-0a51-45e1-9d65-c9527e75136d",
181+
"metadata": {},
182+
"source": [
183+
"The dictionary indeed contains a single entry, a `Person` with `first_name` initialized, and `liast_name` and `age` attributes still set to `None`."
184+
]
185+
},
186+
{
187+
"cell_type": "code",
188+
"execution_count": 8,
189+
"id": "c510d857-6796-48c4-a181-9ce58828cc2f",
190+
"metadata": {},
191+
"outputs": [
192+
{
193+
"data": {
194+
"text/plain": [
195+
"defaultdict(__main__.Person,\n",
196+
" {'gjb': Person(first_name='Geert Jan', last_name=None, age=None)})"
197+
]
198+
},
199+
"execution_count": 8,
200+
"metadata": {},
201+
"output_type": "execute_result"
202+
}
203+
],
204+
"source": [
205+
"people"
206+
]
207+
}
208+
],
209+
"metadata": {
210+
"kernelspec": {
211+
"display_name": "Python 3",
212+
"language": "python",
213+
"name": "python3"
214+
},
215+
"language_info": {
216+
"codemirror_mode": {
217+
"name": "ipython",
218+
"version": 3
219+
},
220+
"file_extension": ".py",
221+
"mimetype": "text/x-python",
222+
"name": "python",
223+
"nbconvert_exporter": "python",
224+
"pygments_lexer": "ipython3",
225+
"version": "3.9.5"
226+
},
227+
"toc-autonumbering": true
228+
},
229+
"nbformat": 4,
230+
"nbformat_minor": 5
231+
}

0 commit comments

Comments
 (0)