forked from yasoob/intermediatePython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcollections.html
More file actions
288 lines (258 loc) · 22.4 KB
/
Copy pathcollections.html
File metadata and controls
288 lines (258 loc) · 22.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Collections</title>
<link rel="stylesheet" href="_static/epub.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
</head>
<body role="document">
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="enumerate.html" title="Enumerate"
accesskey="N">next</a></li>
<li class="right" >
<a href="virtual_environment.html" title="Virtual Environment"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Python Tips 0.1 documentation</a> »</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="body" role="main">
<div class="section" id="collections">
<h1>Collections</h1>
<p>Python ships with a module that contains a number of container data
types called Collections. We will talk about a few of them and discuss
their usefullness.</p>
<p>The ones which we will talk about are:</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">defaultdict</span></code></li>
<li><code class="docutils literal"><span class="pre">counter</span></code></li>
<li><code class="docutils literal"><span class="pre">deque</span></code></li>
<li><code class="docutils literal"><span class="pre">namedtuple</span></code></li>
</ul>
<div class="section" id="defaultdict">
<h2>1.<code class="docutils literal"><span class="pre">defaultdict</span></code></h2>
<p>I personally use defaultdict quite a bit. Unlike <code class="docutils literal"><span class="pre">dict</span></code>, with
<code class="docutils literal"><span class="pre">defaultdict</span></code> you do not need to check whether a key is present or
not. So we can do:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">defaultdict</span>
<span class="n">colours</span> <span class="o">=</span> <span class="p">(</span>
<span class="p">(</span><span class="s">'Yasoob'</span><span class="p">,</span> <span class="s">'Yellow'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ali'</span><span class="p">,</span> <span class="s">'Blue'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Arham'</span><span class="p">,</span> <span class="s">'Green'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ali'</span><span class="p">,</span> <span class="s">'Black'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Yasoob'</span><span class="p">,</span> <span class="s">'Red'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ahmed'</span><span class="p">,</span> <span class="s">'Silver'</span><span class="p">),</span>
<span class="p">)</span>
<span class="n">favourite_colours</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">list</span><span class="p">)</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">colour</span> <span class="ow">in</span> <span class="n">order</span><span class="p">:</span>
<span class="n">favourite_colours</span><span class="p">[</span><span class="n">name</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">colour</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">favourite_colours</span><span class="p">)</span>
<span class="c"># output</span>
<span class="c"># defaultdict(<type 'list'>,</span>
<span class="c"># {'Arham': ['Green'],</span>
<span class="c"># 'Yasoob': ['Yellow', 'Red'],</span>
<span class="c"># 'Ahmed': ['Silver'],</span>
<span class="c"># 'Ali': ['Blue', 'Black']</span>
<span class="c"># })</span>
</pre></div>
</div>
<p>One another very important use case is when you are appending to nested
ists inside a dictionary. If a <code class="docutils literal"><span class="pre">key</span></code> is not already present in the
dictionary then you are greeted with a <code class="docutils literal"><span class="pre">KeyError</span></code>. <code class="docutils literal"><span class="pre">defaultdict</span></code>
allows us to circumvent this issue in a clever way. First let me share
an example using <code class="docutils literal"><span class="pre">dict</span></code> which raises <code class="docutils literal"><span class="pre">KeyError</span></code> and then I will
share a solution using <code class="docutils literal"><span class="pre">defaultdict</span></code>.</p>
<p><strong>Problem:</strong></p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">some_dict</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">some_dict</span><span class="p">[</span><span class="s">'colours'</span><span class="p">][</span><span class="s">'favourite'</span><span class="p">]</span> <span class="o">=</span> <span class="s">"yellow"</span>
<span class="c"># Raises KeyError: 'colours'</span>
</pre></div>
</div>
<p><strong>Solution:</strong></p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">collections</span>
<span class="n">tree</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">collections</span><span class="o">.</span><span class="n">defaultdict</span><span class="p">(</span><span class="n">tree</span><span class="p">)</span>
<span class="n">some_dict</span> <span class="o">=</span> <span class="n">tree</span><span class="p">()</span>
<span class="n">some_dict</span><span class="p">[</span><span class="s">'colours'</span><span class="p">][</span><span class="s">'favourite'</span><span class="p">]</span> <span class="o">=</span> <span class="s">"yellow"</span>
<span class="c"># Works fine</span>
</pre></div>
</div>
<p>You can print the <code class="docutils literal"><span class="pre">some_dict</span></code> using <code class="docutils literal"><span class="pre">json.dumps</span></code>. Here is some
sample code:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">json</span>
<span class="k">print</span><span class="p">(</span><span class="n">json</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">some_dict</span><span class="p">))</span>
<span class="c"># Output: {"colours": {"favourite": "yellow"}}</span>
</pre></div>
</div>
</div>
<div class="section" id="counter">
<h2>2.<code class="docutils literal"><span class="pre">counter</span></code></h2>
<p>Counter allows us to count the occurances of a particular item. For
instance it can be used to count the number of individual favourite
colours:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Counter</span>
<span class="n">colours</span> <span class="o">=</span> <span class="p">(</span>
<span class="p">(</span><span class="s">'Yasoob'</span><span class="p">,</span> <span class="s">'Yellow'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ali'</span><span class="p">,</span> <span class="s">'Blue'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Arham'</span><span class="p">,</span> <span class="s">'Green'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ali'</span><span class="p">,</span> <span class="s">'Black'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Yasoob'</span><span class="p">,</span> <span class="s">'Red'</span><span class="p">),</span>
<span class="p">(</span><span class="s">'Ahmed'</span><span class="p">,</span> <span class="s">'Silver'</span><span class="p">),</span>
<span class="p">)</span>
<span class="n">favs</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="n">name</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">colour</span> <span class="ow">in</span> <span class="n">colours</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">favs</span><span class="p">)</span>
<span class="c"># Output: Counter({</span>
<span class="c"># 'Yasoob': 2,</span>
<span class="c"># 'Ali': 2,</span>
<span class="c"># 'Arham': 1,</span>
<span class="c"># 'Ahmed': 1</span>
<span class="c"># })</span>
</pre></div>
</div>
<p>We can also count the most common lines in a file using it. For example:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">'filename'</span><span class="p">,</span> <span class="s">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">line_count</span> <span class="o">=</span> <span class="n">Counter</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">line_count</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="deque">
<h2>3.<code class="docutils literal"><span class="pre">deque</span></code></h2>
<p><code class="docutils literal"><span class="pre">deque</span></code> provides you with a double ended queue which means that you
can append and delete elements from either side of the queue. First of
all you have to import the deque module from the collections library:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">deque</span>
</pre></div>
</div>
<p>Now we can instantiate a deque object.</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">()</span>
</pre></div>
</div>
<p>It works like python lists and provides you with somewhat similar
methods as well. For example you can do:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">()</span>
<span class="n">d</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'1'</span><span class="p">)</span>
<span class="n">d</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'2'</span><span class="p">)</span>
<span class="n">d</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">'3'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">d</span><span class="p">))</span>
<span class="c"># Output: 3</span>
<span class="k">print</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c"># Output: '1'</span>
<span class="k">print</span><span class="p">(</span><span class="n">d</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="c"># Output: '3'</span>
</pre></div>
</div>
<p>You can pop values from both sides of the deque:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)])</span>
<span class="k">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">d</span><span class="p">))</span>
<span class="c"># Output: 5</span>
<span class="n">d</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span>
<span class="c"># Output: 0</span>
<span class="n">d</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
<span class="c"># Output: 4</span>
<span class="k">print</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="c"># Output: deque([1, 2, 3])</span>
</pre></div>
</div>
<p>We can also limit the amount of items a deque can hold. By doing this
when we achieve the maximum limit of out deque it will simply pop out
the items from the opposite end. It is better to explain it using an
example so here you go:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">(</span><span class="n">maxlen</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
</pre></div>
</div>
<p>Now whenever you insert values after 30, the leftmost value will be
popped from the list. You can also expand the list in any direction with
new values:</p>
<div class="code python highlight-python"><div class="highlight"><pre><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">])</span>
<span class="n">d</span><span class="o">.</span><span class="n">extendleft</span><span class="p">([</span><span class="mi">0</span><span class="p">])</span>
<span class="n">d</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="c"># Output: deque([0, 1, 2, 3, 4, 5, 6, 7, 8])</span>
</pre></div>
</div>
<p>This was just a quick drive through the <code class="docutils literal"><span class="pre">collections</span></code> module. Make
sure you read the official documentation after reading this.</p>
</div>
<div class="section" id="namedtuple">
<h2>4.<code class="docutils literal"><span class="pre">namedtuple</span></code></h2>
<p>You might already be acquainted with tuples. A tuple is a lightweight
object type which allows to store a sequence of immutable Python
objects. They are just like lists but have a few key differences. The
major one is that unlike lists, <strong>you can not change a value in a
tuple</strong>. In order to access the value in a tuple you use integer indexes
like:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">man</span> <span class="o">=</span> <span class="p">(</span><span class="s">'Ali'</span><span class="p">,</span> <span class="mi">30</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">man</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c"># Output: Ali</span>
</pre></div>
</div>
<p>Well, so now what are <code class="docutils literal"><span class="pre">namedtuples</span></code>? They turn tuples into convenient
containers for simple tasks. With namedtuples you don’t have to use
integer indexes for accessing members of a tuple. You can think of
namedtuples like dictionaries but unlike dictionaries they are
immutable.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="n">Animal</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Animal'</span><span class="p">,</span> <span class="s">'name age type'</span><span class="p">)</span>
<span class="n">perry</span> <span class="o">=</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"perry"</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">31</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"cat"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">perry</span><span class="p">)</span>
<span class="c"># Output: Animal(name='perry', age=31, type='cat')</span>
<span class="k">print</span><span class="p">(</span><span class="n">perry</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
<span class="c"># Output: 'perry'</span>
</pre></div>
</div>
<p>As you can see that now we can access members of a tuple just by their
name using a <code class="docutils literal"><span class="pre">.</span></code>. Let’s disect it a little more. A named tuple has two
required arguments. They are the tuple name and the tuple field_names.
In the above example our tuple name was ‘Animal’ and the tuple
field_names were ‘name’, ‘age’ and ‘cat’. Namedtuple makes your tuples
<strong>self-document</strong>. You can easily understand what is going on by having
a quick glance at your code. And as you are not bound to use integer
indexes to access members of a tuple, it makes it more easy to maintain
your code. Moreover, as <strong>``namedtuple`` instances do not have
per-instance dictionaries</strong>, they are lightweight and require no more
memory than regular tuples. This makes them faster than dictionaries.
However, do remember that as with tuples, <strong>attributes in namedtuples
are immutable</strong>. It means that this would not work:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="n">Animal</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Animal'</span><span class="p">,</span> <span class="s">'name age type'</span><span class="p">)</span>
<span class="n">perry</span> <span class="o">=</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"perry"</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">31</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"cat"</span><span class="p">)</span>
<span class="n">perry</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="mi">42</span>
<span class="c"># Output: Traceback (most recent call last):</span>
<span class="c"># File "", line 1, in</span>
<span class="c"># AttributeError: can't set attribute</span>
</pre></div>
</div>
<p>You should use named tuples to make your code self-documenting. <strong>They
are backwards compatible with normal tuples</strong>. It means that you can use
integer indexes with namedtuples as well:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="n">Animal</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Animal'</span><span class="p">,</span> <span class="s">'name age type'</span><span class="p">)</span>
<span class="n">perry</span> <span class="o">=</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"perry"</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">31</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"cat"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">perry</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="c"># Output: perry</span>
</pre></div>
</div>
<p>Last but not the least, you can convert a namedtuple to a dictionary.
Like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
<span class="n">Animal</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s">'Animal'</span><span class="p">,</span> <span class="s">'name age type'</span><span class="p">)</span>
<span class="n">perry</span> <span class="o">=</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">"perry"</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">31</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="s">"cat"</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
© Copyright 2015, Muhammad Yasoob Ullah Khalid.
</div>
</body>
</html>