-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
545 lines (323 loc) · 367 KB
/
Copy pathatom.xml
File metadata and controls
545 lines (323 loc) · 367 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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Monte's Blog</title>
<subtitle>朝着咸鱼的反方向努力</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://monteyang.cn/"/>
<updated>2020-06-11T03:31:38.077Z</updated>
<id>http://monteyang.cn/</id>
<author>
<name>Monte Yang</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>numpy中的np.ascontiguousarray()函数</title>
<link href="http://monteyang.cn/numpy%E4%B8%AD%E7%9A%84np.ascontiguousarray()%E5%87%BD%E6%95%B0.html"/>
<id>http://monteyang.cn/numpy%E4%B8%AD%E7%9A%84np.ascontiguousarray()%E5%87%BD%E6%95%B0.html</id>
<published>2020-06-10T19:00:48.000Z</published>
<updated>2020-06-11T03:31:38.077Z</updated>
<content type="html"><![CDATA[<p><a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ascontiguousarray.html" target="_blank" rel="external nofollow noopener noreferrer">Numpy文档中的说明</a>:</p><p>“Return a contiguous array (ndim >= 1) in memory (C order).</p><a id="more"></a><h1 id="用途"><a href="#用途" class="headerlink" title="用途"></a>用途</h1><p><strong><code>ascontiguousarray</code>函数将一个内存不连续存储的数组转换为内存连续存储的数组,使得运行速度更快。</strong></p><hr><h1 id="C-order-vs-Fortran-order"><a href="#C-order-vs-Fortran-order" class="headerlink" title="C order vs Fortran order"></a>C order vs Fortran order</h1><ul><li><code>C order</code> 指的是<strong>行优先的顺序(Row-major Order)</strong>,即内存中同行的元素存在一起,</li><li><code>Fortran Order</code>则指的是<strong>列优先的顺序(Column-major Order)</strong>,即内存中同列的元素存在一起。</li></ul><p>Pascal, C,C++,Python都是行优先存储的,而Fortran,MatLab是列优先存储的。</p><hr><h1 id="Contiguous-array"><a href="#Contiguous-array" class="headerlink" title="Contiguous array"></a>Contiguous array</h1><p><code>contiguous array</code>指的是数组在内存中存放的地址也是连续的(注意内存地址实际是一维的)。</p><p>2维数组<code>arr = np.arange(12).reshape(3,4)</code>。数组结构如下</p><p><img data-src="https://pic3.zhimg.com/80/v2-9b0851b0ccac01e3429c226157cdf496_720w.png" alt></p><p>在<strong>内存里中实际存储</strong>如下:</p><p><img data-src="https://pic4.zhimg.com/80/v2-cf83ca95eeec64af57351bbe308f0ca3_720w.png" alt></p><p><code>arr</code>是 <strong>C order</strong> 的,在内存是行优先的。如果想要向下移动一列,则需要跳过3个块(例如,从0到4只需要跳过1,2和3)。</p><p>如果经过转置,<code>arr.T</code>没有了C连续特性,因为内存中元素的地址不变,同一行中的相邻元素在内存中不是连续的:</p><p><img data-src="https://pic4.zhimg.com/80/v2-20d84e8244340e02cc1a6591bd7d3ba3_720w.png" alt></p><p>这时,<code>arr.T</code>变成了<code>Fortran order</code>,因为相邻列中的元素在内存中是相邻存储的。</p><p>从性能上来说,获取内存中相邻的地址比不相邻的地址速度要快很多(从RAM读取一个数值的时候可以连着一起读一块地址中的数值,并且可以保存在Cache中),这意味着对连续数组的操作会快很多。</p><p>由于<code>arr</code>是C连续的,因此对其进行行操作比进行列操作速度要快。通常来说</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.sum(arr, axis=<span class="number">1</span>) <span class="comment"># 按行求和</span></span><br></pre></td></tr></table></figure><p>会比<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.sum(arr, axis=<span class="number">0</span>) <span class="comment"># 按列求和</span></span><br></pre></td></tr></table></figure></p><p>稍微快些。<br>同理,在<code>arr.T</code>上,列操作比行操作会快些。</p><hr><h1 id="使用-np-ascontiguousarray"><a href="#使用-np-ascontiguousarray" class="headerlink" title="使用 np.ascontiguousarray()"></a>使用 <code>np.ascontiguousarray()</code></h1><ul><li>Numpy中,随机初始化的数组默认都是C连续的。</li><li><p>经过不规则的<code>slice</code>操作,则会改变连续性,可能会变成既不是C连续,也不是Fortran连续的。</p></li><li><p>可以通过数组的<code>.flags</code>属性,查看一个数组是C连续还是Fortran连续的</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="meta">>>> </span>arr = np.arange(<span class="number">12</span>).reshape(<span class="number">3</span>, <span class="number">4</span>)</span><br><span class="line"><span class="meta">>>> </span>arr.flags</span><br><span class="line"> C_CONTIGUOUS : <span class="literal">True</span></span><br><span class="line"> F_CONTIGUOUS : <span class="literal">False</span></span><br><span class="line"> OWNDATA : <span class="literal">False</span></span><br><span class="line"> WRITEABLE : <span class="literal">True</span></span><br><span class="line"> ALIGNED : <span class="literal">True</span></span><br><span class="line"> WRITEBACKIFCOPY : <span class="literal">False</span></span><br><span class="line"> UPDATEIFCOPY : <span class="literal">False</span></span><br></pre></td></tr></table></figure><p>从输出可以看到数组<code>arr</code>是C连续的。<br>对<code>arr</code>进行按列的<code>slice</code>操作,不改变每行的值,则还是C连续的:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>arr</span><br><span class="line">array([[ <span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>],</span><br><span class="line"> [ <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>],</span><br><span class="line"> [ <span class="number">8</span>, <span class="number">9</span>, <span class="number">10</span>, <span class="number">11</span>]])</span><br><span class="line"><span class="meta">>>> </span>arr1 = arr[:<span class="number">2</span>, :]</span><br><span class="line"><span class="meta">>>> </span>arr1</span><br><span class="line">array([[ <span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>],</span><br><span class="line"> [ <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>]])</span><br><span class="line"><span class="meta">>>> </span>arr1.flags</span><br><span class="line"> C_CONTIGUOUS : <span class="literal">True</span></span><br><span class="line"> F_CONTIGUOUS : <span class="literal">False</span></span><br><span class="line"> OWNDATA : <span class="literal">False</span></span><br><span class="line"> WRITEABLE : <span class="literal">True</span></span><br><span class="line"> ALIGNED : <span class="literal">True</span></span><br><span class="line"> WRITEBACKIFCOPY : <span class="literal">False</span></span><br><span class="line"> UPDATEIFCOPY : <span class="literal">False</span></span><br></pre></td></tr></table></figure><p>如果进行在行上的<code>slice</code>,则会改变连续性,成为既不C连续,也不Fortran连续的:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">>>> </span>arr1 = arr[:, <span class="number">1</span>:<span class="number">3</span>]</span><br><span class="line"><span class="meta">>>> </span>arr1.flags</span><br><span class="line"> C_CONTIGUOUS : <span class="literal">False</span></span><br><span class="line"> F_CONTIGUOUS : <span class="literal">False</span></span><br><span class="line"> OWNDATA : <span class="literal">False</span></span><br><span class="line"> WRITEABLE : <span class="literal">True</span></span><br><span class="line"> ALIGNED : <span class="literal">True</span></span><br><span class="line"> WRITEBACKIFCOPY : <span class="literal">False</span></span><br><span class="line"> UPDATEIFCOPY : <span class="literal">False</span></span><br></pre></td></tr></table></figure><p>此时利用<code>ascontiguousarray</code>函数,可以将其变为连续的:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="meta">>>> </span>arr2 = np.ascontiguousarray(arr1)</span><br><span class="line"><span class="meta">>>> </span>arr2.flags</span><br><span class="line"> C_CONTIGUOUS : <span class="literal">True</span></span><br><span class="line"> F_CONTIGUOUS : <span class="literal">False</span></span><br><span class="line"> OWNDATA : <span class="literal">True</span></span><br><span class="line"> WRITEABLE : <span class="literal">True</span></span><br><span class="line"> ALIGNED : <span class="literal">True</span></span><br><span class="line"> WRITEBACKIFCOPY : <span class="literal">False</span></span><br><span class="line"> UPDATEIFCOPY : <span class="literal">False</span></span><br></pre></td></tr></table></figure><h1 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h1><ul><li><a href="https://zhuanlan.zhihu.com/p/59767914" target="_blank" rel="external nofollow noopener noreferrer">从Numpy中的ascontiguousarray说起 - 知乎</a></li><li>Numpy文档</li></ul>]]></content>
<summary type="html">
<p><a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.ascontiguousarray.html" target="_blank" rel="external nofollow noopener noreferrer">Numpy文档中的说明</a>:</p>
<p>“Return a contiguous array (ndim &gt;= 1) in memory (C order).</p>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Numpy" scheme="http://monteyang.cn/tags/Numpy/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>Numpy、Pandas、Matplotlib、Keras、scikit-learn速查表</title>
<link href="http://monteyang.cn/Numpy%E3%80%81Pandas%E3%80%81Matplotlib%E3%80%81Keras%E9%80%9F%E6%9F%A5%E8%A1%A8.html"/>
<id>http://monteyang.cn/Numpy%E3%80%81Pandas%E3%80%81Matplotlib%E3%80%81Keras%E9%80%9F%E6%9F%A5%E8%A1%A8.html</id>
<published>2020-06-10T03:30:28.000Z</published>
<updated>2020-06-10T11:37:51.353Z</updated>
<content type="html"><![CDATA[<p>速查表</p><a id="more"></a><h1 id="Numpy"><a href="#Numpy" class="headerlink" title="Numpy"></a>Numpy</h1><p><img data-src="../images/numpy速查表.jpg" alt="numpy速查表"></p><h1 id="Pandas"><a href="#Pandas" class="headerlink" title="Pandas"></a>Pandas</h1><p><img data-src="../images/pandas速查表.jpg" alt="pandas速查表"></p><h1 id="Matplotlib"><a href="#Matplotlib" class="headerlink" title="Matplotlib"></a>Matplotlib</h1><p><img data-src="../images/matplotlib速查表.jpg" alt="matplotlib速查表"></p><h1 id="Keras"><a href="#Keras" class="headerlink" title="Keras"></a>Keras</h1><p><img data-src="../images/keras速查表.jpg" alt="keras速查表"></p><h1 id="Scikit-Learn"><a href="#Scikit-Learn" class="headerlink" title="Scikit-Learn"></a>Scikit-Learn</h1><p><img data-src="../images/sklearn速查表.jpg" alt="sklearn速查表"></p>]]></content>
<summary type="html">
<p>速查表</p>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Numpy" scheme="http://monteyang.cn/tags/Numpy/"/>
<category term="Pandas" scheme="http://monteyang.cn/tags/Pandas/"/>
<category term="Matplotlib" scheme="http://monteyang.cn/tags/Matplotlib/"/>
<category term="Keras" scheme="http://monteyang.cn/tags/Keras/"/>
</entry>
<entry>
<title>Python-100道Numpy练习题</title>
<link href="http://monteyang.cn/Python-100%E9%81%93Numpy%E7%BB%83%E4%B9%A0%E9%A2%98.html"/>
<id>http://monteyang.cn/Python-100%E9%81%93Numpy%E7%BB%83%E4%B9%A0%E9%A2%98.html</id>
<published>2020-06-09T20:11:14.000Z</published>
<updated>2020-06-11T02:50:28.540Z</updated>
<content type="html"><![CDATA[<p>原项目: <a href="https://github.com/rougier/numpy-100" target="_blank" rel="external nofollow noopener noreferrer">https://github.com/rougier/numpy-100</a></p><a id="more"></a><h4 id="1-Import-the-numpy-package-under-the-name-np-★☆☆"><a href="#1-Import-the-numpy-package-under-the-name-np-★☆☆" class="headerlink" title="1. Import the numpy package under the name np (★☆☆)"></a>1. Import the numpy package under the name <code>np</code> (★☆☆)</h4><blockquote><p>导入numpy模块命名为np</p></blockquote><p><code>hint: import … as</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br></pre></td></tr></table></figure></p><h4 id="2-Print-the-numpy-version-and-the-configuration-★☆☆"><a href="#2-Print-the-numpy-version-and-the-configuration-★☆☆" class="headerlink" title="2. Print the numpy version and the configuration (★☆☆)"></a>2. Print the numpy version and the configuration (★☆☆)</h4><blockquote><p>查看numpy版本和配置</p></blockquote><p><code>hint: np.__version__, np.show_config)</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">print(np.__version__)</span><br><span class="line">np.show_config()</span><br></pre></td></tr></table></figure><h4 id="3-Create-a-null-vector-of-size-10-★☆☆"><a href="#3-Create-a-null-vector-of-size-10-★☆☆" class="headerlink" title="3. Create a null vector of size 10 (★☆☆)"></a>3. Create a null vector of size 10 (★☆☆)</h4><blockquote><p>创建一个大小为10的空向量</p></blockquote><p><code>hint: np.zeros</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros(<span class="number">10</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]</span></span><br></pre></td></tr></table></figure><h4 id="4-How-to-find-the-memory-size-of-any-array-★☆☆"><a href="#4-How-to-find-the-memory-size-of-any-array-★☆☆" class="headerlink" title="4. How to find the memory size of any array (★☆☆)"></a>4. How to find the memory size of any array (★☆☆)</h4><blockquote><p>查看数组占用内存大小</p></blockquote><p><code>hint: size, itemsize</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros((<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">print(<span class="string">"%d bytes"</span> % (Z.size * Z.itemsize))</span><br><span class="line"></span><br><span class="line"><span class="comment"># 800 bytes</span></span><br></pre></td></tr></table></figure></p><h4 id="5-How-to-get-the-documentation-of-the-numpy-add-function-from-the-command-line-★☆☆"><a href="#5-How-to-get-the-documentation-of-the-numpy-add-function-from-the-command-line-★☆☆" class="headerlink" title="5. How to get the documentation of the numpy add function from the command line? (★☆☆)"></a>5. How to get the documentation of the numpy add function from the command line? (★☆☆)</h4><blockquote><p>查看numpy中add函数的用法</p></blockquote><p><code>hint: np.info</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">%run `python -c <span class="string">"import numpy; numpy.info(numpy.add)"</span>`</span><br></pre></td></tr></table></figure></p><h4 id="6-Create-a-null-vector-of-size-10-but-the-fifth-value-which-is-1-★☆☆"><a href="#6-Create-a-null-vector-of-size-10-but-the-fifth-value-which-is-1-★☆☆" class="headerlink" title="6. Create a null vector of size 10 but the fifth value which is 1 (★☆☆)"></a>6. Create a null vector of size 10 but the fifth value which is 1 (★☆☆)</h4><blockquote><p>创建一个大小为10的空向量,将第5个值设为1</p></blockquote><p><code>hint: array[4]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros(<span class="number">10</span>)</span><br><span class="line">Z[<span class="number">4</span>] = <span class="number">1</span></span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]</span></span><br></pre></td></tr></table></figure><h4 id="7-Create-a-vector-with-values-ranging-from-10-to-49-★☆☆"><a href="#7-Create-a-vector-with-values-ranging-from-10-to-49-★☆☆" class="headerlink" title="7. Create a vector with values ranging from 10 to 49 (★☆☆)"></a>7. Create a vector with values ranging from 10 to 49 (★☆☆)</h4><blockquote><p>构建一个10到49的序列向量</p></blockquote><p><code>hint: arange</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">10</span>,<span class="number">50</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [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]</span></span><br></pre></td></tr></table></figure></p><h4 id="8-Reverse-a-vector-first-element-becomes-last-★☆☆"><a href="#8-Reverse-a-vector-first-element-becomes-last-★☆☆" class="headerlink" title="8. Reverse a vector (first element becomes last) (★☆☆)"></a>8. Reverse a vector (first element becomes last) (★☆☆)</h4><blockquote><p>将一个数组倒序(最后一个元素成为第一个元素)</p></blockquote><p><code>hint: array[::-1]</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">50</span>)</span><br><span class="line">Z = Z[::<span class="number">-1</span>]</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0]</span></span><br></pre></td></tr></table></figure></p><h4 id="9-Create-a-3x3-matrix-with-values-ranging-from-0-to-8-★☆☆"><a href="#9-Create-a-3x3-matrix-with-values-ranging-from-0-to-8-★☆☆" class="headerlink" title="9. Create a 3x3 matrix with values ranging from 0 to 8 (★☆☆)"></a>9. Create a 3x3 matrix with values ranging from 0 to 8 (★☆☆)</h4><blockquote><p>用0-8这9个数构造一个3x3大小的矩阵</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">9</span>).reshape(<span class="number">3</span>, <span class="number">3</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[0 1 2]</span></span><br><span class="line"><span class="comment"># [3 4 5]</span></span><br><span class="line"><span class="comment"># [6 7 8]]</span></span><br></pre></td></tr></table></figure><h4 id="10-Find-indices-of-non-zero-elements-from-1-2-0-0-4-0-★☆☆"><a href="#10-Find-indices-of-non-zero-elements-from-1-2-0-0-4-0-★☆☆" class="headerlink" title="10. Find indices of non-zero elements from [1,2,0,0,4,0] (★☆☆)"></a>10. Find indices of non-zero elements from [1,2,0,0,4,0] (★☆☆)</h4><blockquote><p>从数组[1,2,0,0,4,0]中找出非0元素的下标</p></blockquote><p><code>hint: np.nonzero</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">nz = np.nonzero([<span class="number">1</span>,<span class="number">2</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">4</span>,<span class="number">0</span>])</span><br><span class="line">print(nz)</span><br></pre></td></tr></table></figure><h4 id="11-Create-a-3x3-identity-matrix-★☆☆"><a href="#11-Create-a-3x3-identity-matrix-★☆☆" class="headerlink" title="11. Create a 3x3 identity matrix (★☆☆)"></a>11. Create a 3x3 identity matrix (★☆☆)</h4><blockquote><p>创建3x3的对角矩阵</p></blockquote><p><code>hint: np.eye</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.eye(<span class="number">3</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[1. 0. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 0. 1.]]</span></span><br></pre></td></tr></table></figure></p><h4 id="12-Create-a-3x3x3-array-with-random-values-★☆☆"><a href="#12-Create-a-3x3x3-array-with-random-values-★☆☆" class="headerlink" title="12. Create a 3x3x3 array with random values (★☆☆)"></a>12. Create a 3x3x3 array with random values (★☆☆)</h4><blockquote><p>用随机数创建一个3x3x3的矩阵</p></blockquote><p><code>hint: np.random.random</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random((<span class="number">3</span>,<span class="number">3</span>,<span class="number">3</span>))</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure></p><h4 id="13-Create-a-10x10-array-with-random-values-and-find-the-minimum-and-maximum-values-★☆☆"><a href="#13-Create-a-10x10-array-with-random-values-and-find-the-minimum-and-maximum-values-★☆☆" class="headerlink" title="13. Create a 10x10 array with random values and find the minimum and maximum values (★☆☆)"></a>13. Create a 10x10 array with random values and find the minimum and maximum values (★☆☆)</h4><blockquote><p>创建一个10x10的随机数矩阵,并找到最大值和最小值</p></blockquote><p><code>hint: min, max</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random((<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">Zmin, Zmax = Z.min(), Z.max()</span><br><span class="line">print(Zmin, Zmax)</span><br></pre></td></tr></table></figure><h4 id="14-Create-a-random-vector-of-size-30-and-find-the-mean-value-★☆☆"><a href="#14-Create-a-random-vector-of-size-30-and-find-the-mean-value-★☆☆" class="headerlink" title="14. Create a random vector of size 30 and find the mean value (★☆☆)"></a>14. Create a random vector of size 30 and find the mean value (★☆☆)</h4><blockquote><p>创建一个大小为30的数组,并计算其算术平均值</p></blockquote><p><code>hint: mean</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random(<span class="number">30</span>)</span><br><span class="line">m = Z.mean()</span><br><span class="line">print(m)</span><br></pre></td></tr></table></figure><h4 id="15-Create-a-2d-array-with-1-on-the-border-and-0-inside-★☆☆"><a href="#15-Create-a-2d-array-with-1-on-the-border-and-0-inside-★☆☆" class="headerlink" title="15. Create a 2d array with 1 on the border and 0 inside (★☆☆)"></a>15. Create a 2d array with 1 on the border and 0 inside (★☆☆)</h4><blockquote><p>创建一个二维数组,边为1,其余为0 </p></blockquote><p><code>hint: array[1:-1, 1:-1]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.ones((<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">1</span>:<span class="number">-1</span>] = <span class="number">0</span></span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="16-How-to-add-a-border-filled-with-0’s-around-an-existing-array-★☆☆"><a href="#16-How-to-add-a-border-filled-with-0’s-around-an-existing-array-★☆☆" class="headerlink" title="16. How to add a border (filled with 0’s) around an existing array? (★☆☆)"></a>16. How to add a border (filled with 0’s) around an existing array? (★☆☆)</h4><blockquote><p>扩展给定数组的边界</p></blockquote><p><code>hint: np.pad</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">Z = np.ones((<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line">Z = np.pad(Z, pad_width=<span class="number">1</span>, mode=<span class="string">'constant'</span>, constant_values=<span class="number">0</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[0. 0. 0. 0. 0. 0. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 1. 1. 1. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 1. 1. 1. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 1. 1. 1. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 1. 1. 1. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 1. 1. 1. 1. 1. 0.]</span></span><br><span class="line"><span class="comment"># [0. 0. 0. 0. 0. 0. 0.]]</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># Using fancy indexing</span></span><br><span class="line">Z[:, [<span class="number">0</span>, <span class="number">-1</span>]] = <span class="number">0</span></span><br><span class="line">Z[[<span class="number">0</span>, <span class="number">-1</span>], :] = <span class="number">0</span></span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="17-What-is-the-result-of-the-following-expression-★☆☆"><a href="#17-What-is-the-result-of-the-following-expression-★☆☆" class="headerlink" title="17. What is the result of the following expression? (★☆☆)"></a>17. What is the result of the following expression? (★☆☆)</h4><blockquote><p>下列表达式的结果是什么?</p></blockquote><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">0 * np.nan</span><br><span class="line">np.nan == np.nan</span><br><span class="line">np.inf > np.nan</span><br><span class="line"></span><br><span class="line">np.nan - np.nan</span><br><span class="line">np.nan in set([np.nan])</span><br><span class="line">0.3 == 3 * 0.1</span><br></pre></td></tr></table></figure><p><code>hint: NaN = not a number, inf = infinity</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">print(<span class="number">0</span> * np.nan)</span><br><span class="line">print(np.nan == np.nan)</span><br><span class="line">print(np.inf > np.nan)</span><br><span class="line"></span><br><span class="line">print(np.nan - np.nan)</span><br><span class="line">print(np.nan <span class="keyword">in</span> set([np.nan]))</span><br><span class="line">print(<span class="number">0.3</span> == <span class="number">3</span> * <span class="number">0.1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># nan</span></span><br><span class="line"><span class="comment"># False</span></span><br><span class="line"><span class="comment"># False</span></span><br><span class="line"><span class="comment"># nan</span></span><br><span class="line"><span class="comment"># True</span></span><br><span class="line"><span class="comment"># False</span></span><br></pre></td></tr></table></figure><h4 id="18-Create-a-5x5-matrix-with-values-1-2-3-4-just-below-the-diagonal-★☆☆"><a href="#18-Create-a-5x5-matrix-with-values-1-2-3-4-just-below-the-diagonal-★☆☆" class="headerlink" title="18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)"></a>18. Create a 5x5 matrix with values 1,2,3,4 just below the diagonal (★☆☆)</h4><blockquote><p>用1,2,3,4做为对角线的下移一行,来创建5x5的矩阵</p></blockquote><p><code>hint: np.diag</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Z = np.diag(<span class="number">1</span>+np.arange(<span class="number">4</span>),k=<span class="number">-1</span>)</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[0 0 0 0 0]</span></span><br><span class="line"><span class="comment"># [1 0 0 0 0]</span></span><br><span class="line"><span class="comment"># [0 2 0 0 0]</span></span><br><span class="line"><span class="comment"># [0 0 3 0 0]</span></span><br><span class="line"><span class="comment"># [0 0 0 4 0]]</span></span><br></pre></td></tr></table></figure><h4 id="19-Create-a-8x8-matrix-and-fill-it-with-a-checkerboard-pattern-★☆☆"><a href="#19-Create-a-8x8-matrix-and-fill-it-with-a-checkerboard-pattern-★☆☆" class="headerlink" title="19. Create a 8x8 matrix and fill it with a checkerboard pattern (★☆☆)"></a>19. Create a 8x8 matrix and fill it with a checkerboard pattern (★☆☆)</h4><blockquote><p>创建一个类似国际象棋棋盘的8x8的矩阵</p></blockquote><p><code>hint: array[::2]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros((<span class="number">8</span>,<span class="number">8</span>),dtype=int)</span><br><span class="line">Z[<span class="number">1</span>::<span class="number">2</span>,::<span class="number">2</span>] = <span class="number">1</span></span><br><span class="line">Z[::<span class="number">2</span>,<span class="number">1</span>::<span class="number">2</span>] = <span class="number">1</span></span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]]</span></span><br></pre></td></tr></table></figure><h4 id="20-Consider-a-6-7-8-shape-array-what-is-the-index-x-y-z-of-the-100th-element"><a href="#20-Consider-a-6-7-8-shape-array-what-is-the-index-x-y-z-of-the-100th-element" class="headerlink" title="20. Consider a (6,7,8) shape array, what is the index (x,y,z) of the 100th element?"></a>20. Consider a (6,7,8) shape array, what is the index (x,y,z) of the 100th element?</h4><blockquote><p>对一个6x7x8的数组,找出第100个元素的下标</p></blockquote><p><code>hint: np.unravel_index</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">print(np.unravel_index(<span class="number">99</span>,(<span class="number">6</span>,<span class="number">7</span>,<span class="number">8</span>)))</span><br><span class="line"></span><br><span class="line"><span class="comment"># (1, 5, 3)</span></span><br></pre></td></tr></table></figure><h4 id="21-Create-a-checkerboard-8x8-matrix-using-the-tile-function-★☆☆"><a href="#21-Create-a-checkerboard-8x8-matrix-using-the-tile-function-★☆☆" class="headerlink" title="21. Create a checkerboard 8x8 matrix using the tile function (★☆☆)"></a>21. Create a checkerboard 8x8 matrix using the tile function (★☆☆)</h4><blockquote><p>使用tile函数创建一个棋盘</p></blockquote><p><code>hint: np.tile</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Z = np.tile( np.array([[<span class="number">0</span>,<span class="number">1</span>],[<span class="number">1</span>,<span class="number">0</span>]]), (<span class="number">4</span>,<span class="number">4</span>))</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [[0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]</span></span><br><span class="line"><span class="comment"># [0 1 0 1 0 1 0 1]</span></span><br><span class="line"><span class="comment"># [1 0 1 0 1 0 1 0]]</span></span><br></pre></td></tr></table></figure><h4 id="22-Normalize-a-5x5-random-matrix-★☆☆"><a href="#22-Normalize-a-5x5-random-matrix-★☆☆" class="headerlink" title="22. Normalize a 5x5 random matrix (★☆☆)"></a>22. Normalize a 5x5 random matrix (★☆☆)</h4><blockquote><p>标准化一个5x5的随机矩阵</p></blockquote><p><code>hint: (x -mean)/std</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random((<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line">Z = (Z - np.mean (Z)) / (np.std (Z))</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure></p><h4 id="23-Create-a-custom-dtype-that-describes-a-color-as-four-unsigned-bytes-RGBA-★☆☆"><a href="#23-Create-a-custom-dtype-that-describes-a-color-as-four-unsigned-bytes-RGBA-★☆☆" class="headerlink" title="23. Create a custom dtype that describes a color as four unsigned bytes (RGBA) (★☆☆)"></a>23. Create a custom dtype that describes a color as four unsigned bytes (RGBA) (★☆☆)</h4><blockquote><p>自定义一个用 unsigned bytes 表示RGBA颜色的dtype类型</p></blockquote><p><code>hint: np.dtype</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">color = np.dtype([(<span class="string">"r"</span>, np.ubyte, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">"g"</span>, np.ubyte, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">"b"</span>, np.ubyte, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">"a"</span>, np.ubyte, <span class="number">1</span>)])</span><br></pre></td></tr></table></figure><h4 id="24-Multiply-a-5x3-matrix-by-a-3x2-matrix-real-matrix-product-★☆☆"><a href="#24-Multiply-a-5x3-matrix-by-a-3x2-matrix-real-matrix-product-★☆☆" class="headerlink" title="24. Multiply a 5x3 matrix by a 3x2 matrix (real matrix product) (★☆☆)"></a>24. Multiply a 5x3 matrix by a 3x2 matrix (real matrix product) (★☆☆)</h4><blockquote><p>计算5x3和3x2矩阵的内积(点乘)</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.dot(np.ones((<span class="number">5</span>,<span class="number">3</span>)), np.ones((<span class="number">3</span>,<span class="number">2</span>)))</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Alternative solution, in Python 3.5 and above</span></span><br><span class="line">Z = np.ones((<span class="number">5</span>,<span class="number">3</span>)) @ np.ones((<span class="number">3</span>,<span class="number">2</span>))</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="25-Given-a-1D-array-negate-all-elements-which-are-between-3-and-8-in-place-★☆☆"><a href="#25-Given-a-1D-array-negate-all-elements-which-are-between-3-and-8-in-place-★☆☆" class="headerlink" title="25. Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)"></a>25. Given a 1D array, negate all elements which are between 3 and 8, in place. (★☆☆)</h4><blockquote><p>反转一维数组中大于3小于8的所有元素</p></blockquote><p><code>hint: >, <</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Evgeni Burovski</span></span><br><span class="line"></span><br><span class="line">Z = np.arange(<span class="number">11</span>)</span><br><span class="line">Z[(<span class="number">3</span> < Z) & (Z <= <span class="number">8</span>)] *= <span class="number">-1</span></span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="26-What-is-the-output-of-the-following-script-★☆☆"><a href="#26-What-is-the-output-of-the-following-script-★☆☆" class="headerlink" title="26. What is the output of the following script? (★☆☆)"></a>26. What is the output of the following script? (★☆☆)</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jake VanderPlas</span></span><br><span class="line"></span><br><span class="line">print(sum(range(<span class="number">5</span>),<span class="number">-1</span>))</span><br><span class="line"><span class="keyword">from</span> numpy <span class="keyword">import</span> *</span><br><span class="line">print(sum(range(<span class="number">5</span>),<span class="number">-1</span>))</span><br></pre></td></tr></table></figure><p><code>hint: np.sum</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jake VanderPlas</span></span><br><span class="line"></span><br><span class="line">print(sum(range(<span class="number">5</span>), <span class="number">-1</span>)) <span class="comment"># sum(range(5)) + (-1)</span></span><br><span class="line"></span><br><span class="line">print(np.sum(range(<span class="number">5</span>),<span class="number">-1</span>))</span><br><span class="line"><span class="comment"># 在选定的轴上执行求和。如果是默认值(axis=None),就会在所有的轴上执行求和。</span></span><br><span class="line"><span class="comment"># axis=-1表示是倒数第一个轴。</span></span><br></pre></td></tr></table></figure><h4 id="27-Consider-an-integer-vector-Z-which-of-these-expressions-are-legal-★☆☆"><a href="#27-Consider-an-integer-vector-Z-which-of-these-expressions-are-legal-★☆☆" class="headerlink" title="27. Consider an integer vector Z, which of these expressions are legal? (★☆☆)"></a>27. Consider an integer vector Z, which of these expressions are legal? (★☆☆)</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Z**Z</span><br><span class="line"><span class="number">2</span> << Z >> <span class="number">2</span></span><br><span class="line"></span><br><span class="line">Z <- Z</span><br><span class="line"><span class="number">1j</span>*Z</span><br><span class="line">Z/<span class="number">1</span>/<span class="number">1</span></span><br><span class="line">Z<Z>Z</span><br></pre></td></tr></table></figure><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Z**Z</span><br><span class="line"><span class="number">2</span> << Z >> <span class="number">2</span></span><br><span class="line"></span><br><span class="line">Z <- Z</span><br><span class="line"><span class="number">1j</span>*Z</span><br><span class="line">Z/<span class="number">1</span>/<span class="number">1</span></span><br><span class="line">Z<Z>Z</span><br></pre></td></tr></table></figure><h4 id="28-What-are-the-result-of-the-following-expressions"><a href="#28-What-are-the-result-of-the-following-expressions" class="headerlink" title="28. What are the result of the following expressions?"></a>28. What are the result of the following expressions?</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">np.array(<span class="number">0</span>) / np.array(<span class="number">0</span>)</span><br><span class="line">np.array(<span class="number">0</span>) // np.array(<span class="number">0</span>)</span><br><span class="line">np.array([np.nan]).astype(int).astype(float)</span><br></pre></td></tr></table></figure><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">print(np.array(<span class="number">0</span>) / np.array(<span class="number">0</span>))</span><br><span class="line">print(np.array(<span class="number">0</span>) // np.array(<span class="number">0</span>))</span><br><span class="line">print(np.array([np.nan]).astype(int).astype(float))</span><br></pre></td></tr></table></figure><h4 id="29-How-to-round-away-from-zero-a-float-array-★☆☆"><a href="#29-How-to-round-away-from-zero-a-float-array-★☆☆" class="headerlink" title="29. How to round away from zero a float array ? (★☆☆)"></a>29. How to round away from zero a float array ? (★☆☆)</h4><blockquote><p>浮点数数组取整</p></blockquote><p><code>hint: np.uniform, np.copysign, np.ceil, np.abs, np.where</code><br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Charles R Harris</span></span><br><span class="line"></span><br><span class="line">Z = np.random.uniform(<span class="number">-10</span>,+<span class="number">10</span>,<span class="number">10</span>)</span><br><span class="line">print(np.copysign(np.ceil(np.abs(Z)), Z))</span><br><span class="line"></span><br><span class="line"><span class="comment"># More readable but less efficient</span></span><br><span class="line">print(np.where(Z><span class="number">0</span>, np.ceil(Z), np.floor(Z)))</span><br></pre></td></tr></table></figure></p><h4 id="30-How-to-find-common-values-between-two-arrays-★☆☆"><a href="#30-How-to-find-common-values-between-two-arrays-★☆☆" class="headerlink" title="30. How to find common values between two arrays? (★☆☆)"></a>30. How to find common values between two arrays? (★☆☆)</h4><blockquote><p>两个数组的交集</p></blockquote><p><code>hint: np.intersect1d</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z1 = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,<span class="number">10</span>)</span><br><span class="line">Z2 = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,<span class="number">10</span>)</span><br><span class="line">print(np.intersect1d(Z1,Z2))</span><br></pre></td></tr></table></figure><h4 id="31-How-to-ignore-all-numpy-warnings-not-recommended-★☆☆"><a href="#31-How-to-ignore-all-numpy-warnings-not-recommended-★☆☆" class="headerlink" title="31. How to ignore all numpy warnings (not recommended)? (★☆☆)"></a>31. How to ignore all numpy warnings (not recommended)? (★☆☆)</h4><blockquote><p>忽略numpy的警告</p></blockquote><p><code>hint: np.seterr, np.errstate</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Suicide mode on</span></span><br><span class="line">defaults = np.seterr(all=<span class="string">"ignore"</span>)</span><br><span class="line">Z = np.ones(<span class="number">1</span>) / <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Back to sanity</span></span><br><span class="line">_ = np.seterr(**defaults)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Equivalently with a context manager</span></span><br><span class="line"><span class="keyword">with</span> np.errstate(all=<span class="string">"ignore"</span>):</span><br><span class="line"> np.arange(<span class="number">3</span>) / <span class="number">0</span></span><br></pre></td></tr></table></figure><h4 id="32-Is-the-following-expressions-true-★☆☆"><a href="#32-Is-the-following-expressions-true-★☆☆" class="headerlink" title="32. Is the following expressions true? (★☆☆)"></a>32. Is the following expressions true? (★☆☆)</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.sqrt(<span class="number">-1</span>) == np.emath.sqrt(<span class="number">-1</span>)</span><br></pre></td></tr></table></figure><p><code>hint: imaginary number</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.sqrt(<span class="number">-1</span>) == np.emath.sqrt(<span class="number">-1</span>)</span><br></pre></td></tr></table></figure><h4 id="33-How-to-get-the-dates-of-yesterday-today-and-tomorrow-★☆☆"><a href="#33-How-to-get-the-dates-of-yesterday-today-and-tomorrow-★☆☆" class="headerlink" title="33. How to get the dates of yesterday, today and tomorrow? (★☆☆)"></a>33. How to get the dates of yesterday, today and tomorrow? (★☆☆)</h4><blockquote><p>获取今天,昨天,明天的日期</p></blockquote><p><code>hint: np.datetime64, np.timedelta64</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">yesterday = np.datetime64(<span class="string">'today'</span>) - np.timedelta64(<span class="number">1</span>)</span><br><span class="line">today = np.datetime64(<span class="string">'today'</span>)</span><br><span class="line">tomorrow = np.datetime64(<span class="string">'today'</span>) + np.timedelta64(<span class="number">1</span>)</span><br></pre></td></tr></table></figure><h4 id="34-How-to-get-all-the-dates-corresponding-to-the-month-of-July-2016-★★☆"><a href="#34-How-to-get-all-the-dates-corresponding-to-the-month-of-July-2016-★★☆" class="headerlink" title="34. How to get all the dates corresponding to the month of July 2016? (★★☆)"></a>34. How to get all the dates corresponding to the month of July 2016? (★★☆)</h4><blockquote><p>获取2016年7月的所有日期</p></blockquote><p><code>hint: np.arange(dtype=datetime64['D'])</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="string">'2016-07'</span>, <span class="string">'2016-08'</span>, dtype=<span class="string">'datetime64[D]'</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="35-How-to-compute-A-B-A-2-in-place-without-copy-★★☆"><a href="#35-How-to-compute-A-B-A-2-in-place-without-copy-★★☆" class="headerlink" title="35. How to compute ((A+B)*(-A/2)) in place (without copy)? (★★☆)"></a>35. How to compute ((A+B)*(-A/2)) in place (without copy)? (★★☆)</h4><blockquote><p>避免复制操作的计算</p></blockquote><p><code>hint: np.add(out=), np.negative(out=), np.multiply(out=), np.divide(out=)</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">A = np.ones(<span class="number">3</span>)*<span class="number">1</span></span><br><span class="line">B = np.ones(<span class="number">3</span>)*<span class="number">2</span></span><br><span class="line">C = np.ones(<span class="number">3</span>)*<span class="number">3</span></span><br><span class="line">np.add(A,B,out=B)</span><br><span class="line">np.divide(A,<span class="number">2</span>,out=A)</span><br><span class="line">np.negative(A,out=A)</span><br><span class="line">np.multiply(A,B,out=A)</span><br></pre></td></tr></table></figure><h4 id="36-Extract-the-integer-part-of-a-random-array-of-positive-numbers-using-4-different-methods-★★☆"><a href="#36-Extract-the-integer-part-of-a-random-array-of-positive-numbers-using-4-different-methods-★★☆" class="headerlink" title="36. Extract the integer part of a random array of positive numbers using 4 different methods (★★☆)"></a>36. Extract the integer part of a random array of positive numbers using 4 different methods (★★☆)</h4><blockquote><p>用五种方法抽取随机矩阵的整数部分</p></blockquote><p><code>hint: %, np.floor, astype, np.trunc</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.uniform(<span class="number">0</span>,<span class="number">10</span>,<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">print(Z - Z%<span class="number">1</span>)</span><br><span class="line">print(Z // <span class="number">1</span>)</span><br><span class="line">print(np.floor(Z))</span><br><span class="line">print(Z.astype(int))</span><br><span class="line">print(np.trunc(Z))</span><br></pre></td></tr></table></figure><h4 id="37-Create-a-5x5-matrix-with-row-values-ranging-from-0-to-4-★★☆"><a href="#37-Create-a-5x5-matrix-with-row-values-ranging-from-0-to-4-★★☆" class="headerlink" title="37. Create a 5x5 matrix with row values ranging from 0 to 4 (★★☆)"></a>37. Create a 5x5 matrix with row values ranging from 0 to 4 (★★☆)</h4><blockquote><p>创建一个5x5每行为0到4的矩阵</p></blockquote><p><code>hint: np.arange</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros((<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line">Z += np.arange(<span class="number">5</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="38-Consider-a-generator-function-that-generates-10-integers-and-use-it-to-build-an-array-★☆☆"><a href="#38-Consider-a-generator-function-that-generates-10-integers-and-use-it-to-build-an-array-★☆☆" class="headerlink" title="38. Consider a generator function that generates 10 integers and use it to build an array (★☆☆)"></a>38. Consider a generator function that generates 10 integers and use it to build an array (★☆☆)</h4><blockquote><p>使用生成器创建一个大小为10的数组</p></blockquote><p><code>hint: np.fromiter</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">generate</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">for</span> x <span class="keyword">in</span> range(<span class="number">10</span>):</span><br><span class="line"> <span class="keyword">yield</span> x</span><br><span class="line">Z = np.fromiter(generate(),dtype=float,count=<span class="number">-1</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="39-Create-a-vector-of-size-10-with-values-ranging-from-0-to-1-both-excluded-★★☆"><a href="#39-Create-a-vector-of-size-10-with-values-ranging-from-0-to-1-both-excluded-★★☆" class="headerlink" title="39. Create a vector of size 10 with values ranging from 0 to 1, both excluded (★★☆)"></a>39. Create a vector of size 10 with values ranging from 0 to 1, both excluded (★★☆)</h4><blockquote><p>创建一个大小为10的数组,值为0到1之间,不包含0和1</p></blockquote><p><code>hint: np.linspace</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Z = np.linspace(<span class="number">0</span>,<span class="number">1</span>,<span class="number">11</span>,endpoint=<span class="literal">False</span>)[<span class="number">1</span>:]</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># [0.09090909 0.18181818 0.27272727 0.36363636 0.45454545 0.54545455</span></span><br><span class="line"><span class="comment"># 0.63636364 0.72727273 0.81818182 0.90909091]</span></span><br></pre></td></tr></table></figure><h4 id="40-Create-a-random-vector-of-size-10-and-sort-it-★★☆"><a href="#40-Create-a-random-vector-of-size-10-and-sort-it-★★☆" class="headerlink" title="40. Create a random vector of size 10 and sort it (★★☆)"></a>40. Create a random vector of size 10 and sort it (★★☆)</h4><blockquote><p>创建一个大小为10的数组并排序</p></blockquote><p><code>hint: sort</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random(<span class="number">10</span>)</span><br><span class="line">Z.sort()</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="41-How-to-sum-a-small-array-faster-than-np-sum-★★☆"><a href="#41-How-to-sum-a-small-array-faster-than-np-sum-★★☆" class="headerlink" title="41. How to sum a small array faster than np.sum? (★★☆)"></a>41. How to sum a small array faster than np.sum? (★★☆)</h4><blockquote><p>对一个小数组用比np.sum快的方法求和</p></blockquote><p><code>hint: np.add.reduce</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Evgeni Burovski</span></span><br><span class="line"></span><br><span class="line">Z = np.arange(<span class="number">10</span>)</span><br><span class="line">np.add.reduce(Z)</span><br></pre></td></tr></table></figure><h4 id="42-Consider-two-random-array-A-and-B-check-if-they-are-equal-★★☆"><a href="#42-Consider-two-random-array-A-and-B-check-if-they-are-equal-★★☆" class="headerlink" title="42. Consider two random array A and B, check if they are equal (★★☆)"></a>42. Consider two random array A and B, check if they are equal (★★☆)</h4><blockquote><p>比较两个随机数组是否相等</p></blockquote><p><code>hint: np.allclose, np.array_equal</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">A = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,<span class="number">5</span>)</span><br><span class="line">B = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,<span class="number">5</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Assuming identical shape of the arrays and a tolerance for the comparison of values</span></span><br><span class="line">equal = np.allclose(A,B)</span><br><span class="line">print(equal)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Checking both the shape and the element values, no tolerance (values have to be exactly equal)</span></span><br><span class="line">equal = np.array_equal(A,B)</span><br><span class="line">print(equal)</span><br></pre></td></tr></table></figure><h4 id="43-Make-an-array-immutable-read-only-★★☆"><a href="#43-Make-an-array-immutable-read-only-★★☆" class="headerlink" title="43. Make an array immutable (read-only) (★★☆)"></a>43. Make an array immutable (read-only) (★★☆)</h4><blockquote><p>创建一个不可变数组(只读)</p></blockquote><p><code>hint: flags.writeable</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros(<span class="number">10</span>)</span><br><span class="line">Z.flags.writeable = <span class="literal">False</span></span><br><span class="line">Z[<span class="number">0</span>] = <span class="number">1</span></span><br></pre></td></tr></table></figure><h4 id="44-Consider-a-random-10x2-matrix-representing-cartesian-coordinates-convert-them-to-polar-coordinates-★★☆"><a href="#44-Consider-a-random-10x2-matrix-representing-cartesian-coordinates-convert-them-to-polar-coordinates-★★☆" class="headerlink" title="44. Consider a random 10x2 matrix representing cartesian coordinates, convert them to polar coordinates (★★☆)"></a>44. Consider a random 10x2 matrix representing cartesian coordinates, convert them to polar coordinates (★★☆)</h4><blockquote><p>创建一个大小为10x2的矩阵来代表笛卡儿坐标,并转为极坐标</p></blockquote><p><code>hint: np.sqrt, np.arctan2</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random((<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">X,Y = Z[:,<span class="number">0</span>], Z[:,<span class="number">1</span>]</span><br><span class="line">R = np.sqrt(X**<span class="number">2</span>+Y**<span class="number">2</span>)</span><br><span class="line">T = np.arctan2(Y,X)</span><br><span class="line">print(R)</span><br><span class="line">print(T)</span><br></pre></td></tr></table></figure><h4 id="45-Create-random-vector-of-size-10-and-replace-the-maximum-value-by-0-★★☆"><a href="#45-Create-random-vector-of-size-10-and-replace-the-maximum-value-by-0-★★☆" class="headerlink" title="45. Create random vector of size 10 and replace the maximum value by 0 (★★☆)"></a>45. Create random vector of size 10 and replace the maximum value by 0 (★★☆)</h4><blockquote><p>创建一个大小为10的数组并把最大值设为0</p></blockquote><p><code>hint: argmax</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random(<span class="number">10</span>)</span><br><span class="line">Z[Z.argmax()] = <span class="number">0</span></span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="46-Create-a-structured-array-with-x-and-y-coordinates-covering-the-0-1-x-0-1-area-★★☆"><a href="#46-Create-a-structured-array-with-x-and-y-coordinates-covering-the-0-1-x-0-1-area-★★☆" class="headerlink" title="46. Create a structured array with x and y coordinates covering the [0,1]x[0,1] area (★★☆)"></a>46. Create a structured array with <code>x</code> and <code>y</code> coordinates covering the [0,1]x[0,1] area (★★☆)</h4><blockquote><p>创建一个结构化数组,其x和y坐标覆盖[0,1] x [0,1]区域</p></blockquote><p><code>hint: np.meshgrid</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros((<span class="number">5</span>,<span class="number">5</span>), [(<span class="string">'x'</span>,float),(<span class="string">'y'</span>,float)])</span><br><span class="line">Z[<span class="string">'x'</span>], Z[<span class="string">'y'</span>] = np.meshgrid(np.linspace(<span class="number">0</span>,<span class="number">1</span>,<span class="number">5</span>),</span><br><span class="line"> np.linspace(<span class="number">0</span>,<span class="number">1</span>,<span class="number">5</span>))</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="47-Given-two-arrays-X-and-Y-construct-the-Cauchy-matrix-C-Cij-1-xi-yj"><a href="#47-Given-two-arrays-X-and-Y-construct-the-Cauchy-matrix-C-Cij-1-xi-yj" class="headerlink" title="47. Given two arrays, X and Y, construct the Cauchy matrix C (Cij =1/(xi - yj))"></a>47. Given two arrays, X and Y, construct the Cauchy matrix C (Cij =1/(xi - yj))</h4><blockquote><p>给定两个数组X和Y,构造柯西矩阵</p></blockquote><p><code>hint: np.subtract.outer</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Evgeni Burovski</span></span><br><span class="line"></span><br><span class="line">X = np.arange(<span class="number">8</span>)</span><br><span class="line">Y = X + <span class="number">0.5</span></span><br><span class="line">C = <span class="number">1.0</span> / np.subtract.outer(X, Y)</span><br><span class="line">print(np.linalg.det(C))</span><br></pre></td></tr></table></figure><h4 id="48-Print-the-minimum-and-maximum-representable-value-for-each-numpy-scalar-type-★★☆"><a href="#48-Print-the-minimum-and-maximum-representable-value-for-each-numpy-scalar-type-★★☆" class="headerlink" title="48. Print the minimum and maximum representable value for each numpy scalar type (★★☆)"></a>48. Print the minimum and maximum representable value for each numpy scalar type (★★☆)</h4><blockquote><p>显示机器能处理的数值的范围</p></blockquote><p><code>hint: np.iinfo, np.finfo, eps</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> dtype <span class="keyword">in</span> [np.int8, np.int32, np.int64]:</span><br><span class="line"> print(np.iinfo(dtype).min)</span><br><span class="line"> print(np.iinfo(dtype).max)</span><br><span class="line"><span class="keyword">for</span> dtype <span class="keyword">in</span> [np.float32, np.float64]:</span><br><span class="line"> print(np.finfo(dtype).min)</span><br><span class="line"> print(np.finfo(dtype).max)</span><br><span class="line"> print(np.finfo(dtype).eps)</span><br></pre></td></tr></table></figure><h4 id="49-How-to-print-all-the-values-of-an-array-★★☆"><a href="#49-How-to-print-all-the-values-of-an-array-★★☆" class="headerlink" title="49. How to print all the values of an array? (★★☆)"></a>49. How to print all the values of an array? (★★☆)</h4><blockquote><p>显示array中所有的值</p></blockquote><p><code>hint: np.set_printoptions</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">np.set_printoptions(threshold=np.nan)</span><br><span class="line">Z = np.zeros((<span class="number">16</span>,<span class="number">16</span>))</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="50-How-to-find-the-closest-value-to-a-given-scalar-in-a-vector-★★☆"><a href="#50-How-to-find-the-closest-value-to-a-given-scalar-in-a-vector-★★☆" class="headerlink" title="50. How to find the closest value (to a given scalar) in a vector? (★★☆)"></a>50. How to find the closest value (to a given scalar) in a vector? (★★☆)</h4><blockquote><p>如何在向量中找到指定范围的最近值?</p></blockquote><p><code>hint: argmin</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">100</span>)</span><br><span class="line">v = np.random.uniform(<span class="number">0</span>,<span class="number">100</span>)</span><br><span class="line">index = (np.abs(Z-v)).argmin()</span><br><span class="line">print(Z[index])</span><br></pre></td></tr></table></figure><h4 id="51-Create-a-structured-array-representing-a-position-x-y-and-a-color-r-g-b-★★☆"><a href="#51-Create-a-structured-array-representing-a-position-x-y-and-a-color-r-g-b-★★☆" class="headerlink" title="51. Create a structured array representing a position (x,y) and a color (r,g,b) (★★☆)"></a>51. Create a structured array representing a position (x,y) and a color (r,g,b) (★★☆)</h4><blockquote><p>构建一个代表位置 (x,y) 和 颜色 (r,g,b)的矩阵</p></blockquote><p><code>hint: dtype</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.zeros(<span class="number">10</span>, [ (<span class="string">'position'</span>, [ (<span class="string">'x'</span>, float, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">'y'</span>, float, <span class="number">1</span>)]),</span><br><span class="line"> (<span class="string">'color'</span>, [ (<span class="string">'r'</span>, float, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">'g'</span>, float, <span class="number">1</span>),</span><br><span class="line"> (<span class="string">'b'</span>, float, <span class="number">1</span>)])])</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="52-Consider-a-random-vector-with-shape-100-2-representing-coordinates-find-point-by-point-distances-★★☆"><a href="#52-Consider-a-random-vector-with-shape-100-2-representing-coordinates-find-point-by-point-distances-★★☆" class="headerlink" title="52. Consider a random vector with shape (100,2) representing coordinates, find point by point distances (★★☆)"></a>52. Consider a random vector with shape (100,2) representing coordinates, find point by point distances (★★☆)</h4><blockquote><p>用一个100*2的随机向量来表示坐标,计算点到点的距离</p></blockquote><p><code>hint: np.atleast_2d, T, np.sqrt</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.random((<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">X,Y = np.atleast_2d(Z[:,<span class="number">0</span>], Z[:,<span class="number">1</span>])</span><br><span class="line">D = np.sqrt( (X-X.T)**<span class="number">2</span> + (Y-Y.T)**<span class="number">2</span>)</span><br><span class="line">print(D)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Much faster with scipy</span></span><br><span class="line"><span class="keyword">import</span> scipy</span><br><span class="line"><span class="comment"># Thanks Gavin Heverly-Coulson (#issue 1)</span></span><br><span class="line"><span class="keyword">import</span> scipy.spatial</span><br><span class="line"></span><br><span class="line">Z = np.random.random((<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">D = scipy.spatial.distance.cdist(Z,Z)</span><br><span class="line">print(D)</span><br></pre></td></tr></table></figure><h4 id="53-How-to-convert-a-float-32-bits-array-into-an-integer-32-bits-in-place"><a href="#53-How-to-convert-a-float-32-bits-array-into-an-integer-32-bits-in-place" class="headerlink" title="53. How to convert a float (32 bits) array into an integer (32 bits) in place?"></a>53. How to convert a float (32 bits) array into an integer (32 bits) in place?</h4><blockquote><p>如何将浮点数(32位)数组转换为整数(32位)数组</p></blockquote><p><code>hint: view and [:] =</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Thanks Vikas (https://stackoverflow.com/a/10622758/5989906)</span></span><br><span class="line"><span class="comment"># & unutbu (https://stackoverflow.com/a/4396247/5989906)</span></span><br><span class="line">Z = (np.random.rand(<span class="number">10</span>)*<span class="number">100</span>).astype(np.float32)</span><br><span class="line">Y = Z.view(np.int32)</span><br><span class="line">Y[:] = Z</span><br><span class="line">print(Y)</span><br></pre></td></tr></table></figure><h4 id="54-How-to-read-the-following-file-★★☆"><a href="#54-How-to-read-the-following-file-★★☆" class="headerlink" title="54. How to read the following file? (★★☆)"></a>54. How to read the following file? (★★☆)</h4><blockquote><p>从文件中读取数据</p></blockquote><figure class="highlight angelscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span></span><br><span class="line"><span class="number">6</span>, , , <span class="number">7</span>, <span class="number">8</span></span><br><span class="line"> , , <span class="number">9</span>,<span class="number">10</span>,<span class="number">11</span></span><br></pre></td></tr></table></figure><p><code>hint: np.genfromtxt</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> io <span class="keyword">import</span> StringIO</span><br><span class="line"></span><br><span class="line"><span class="comment"># Fake file</span></span><br><span class="line">s = StringIO(<span class="string">'''1, 2, 3, 4, 5</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> 6, , , 7, 8</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"> , , 9,10,11</span></span><br><span class="line"><span class="string">'''</span>)</span><br><span class="line">Z = np.genfromtxt(s, delimiter=<span class="string">","</span>, dtype=np.int)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="55-What-is-the-equivalent-of-enumerate-for-numpy-arrays-★★☆"><a href="#55-What-is-the-equivalent-of-enumerate-for-numpy-arrays-★★☆" class="headerlink" title="55. What is the equivalent of enumerate for numpy arrays? (★★☆)"></a>55. What is the equivalent of enumerate for numpy arrays? (★★☆)</h4><blockquote><p>什么是numpy数组的枚举</p></blockquote><p><code>hint: np.ndenumerate, np.ndindex</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">9</span>).reshape(<span class="number">3</span>,<span class="number">3</span>)</span><br><span class="line"><span class="keyword">for</span> index, value <span class="keyword">in</span> np.ndenumerate(Z):</span><br><span class="line"> print(index, value)</span><br><span class="line"><span class="keyword">for</span> index <span class="keyword">in</span> np.ndindex(Z.shape):</span><br><span class="line"> print(index, Z[index])</span><br></pre></td></tr></table></figure><h4 id="56-Generate-a-generic-2D-Gaussian-like-array-★★☆"><a href="#56-Generate-a-generic-2D-Gaussian-like-array-★★☆" class="headerlink" title="56. Generate a generic 2D Gaussian-like array (★★☆)"></a>56. Generate a generic 2D Gaussian-like array (★★☆)</h4><blockquote><p>生成二维高斯数组</p></blockquote><p><code>hint: np.meshgrid, np.exp</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">X, Y = np.meshgrid(np.linspace(<span class="number">-1</span>,<span class="number">1</span>,<span class="number">10</span>), np.linspace(<span class="number">-1</span>,<span class="number">1</span>,<span class="number">10</span>))</span><br><span class="line">D = np.sqrt(X*X+Y*Y)</span><br><span class="line">sigma, mu = <span class="number">1.0</span>, <span class="number">0.0</span></span><br><span class="line">G = np.exp(-( (D-mu)**<span class="number">2</span> / ( <span class="number">2.0</span> * sigma**<span class="number">2</span> ) ) )</span><br><span class="line">print(G)</span><br></pre></td></tr></table></figure><h4 id="57-How-to-randomly-place-p-elements-in-a-2D-array-★★☆"><a href="#57-How-to-randomly-place-p-elements-in-a-2D-array-★★☆" class="headerlink" title="57. How to randomly place p elements in a 2D array? (★★☆)"></a>57. How to randomly place p elements in a 2D array? (★★☆)</h4><blockquote><p>将元素P随机的放入二维数组中</p></blockquote><p><code>hint: np.put, np.random.choice</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Divakar</span></span><br><span class="line"></span><br><span class="line">n = <span class="number">10</span></span><br><span class="line">p = <span class="number">3</span></span><br><span class="line">Z = np.zeros((n,n))</span><br><span class="line">np.put(Z, np.random.choice(range(n*n), p, replace=<span class="literal">False</span>),<span class="number">1</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="58-Subtract-the-mean-of-each-row-of-a-matrix-★★☆"><a href="#58-Subtract-the-mean-of-each-row-of-a-matrix-★★☆" class="headerlink" title="58. Subtract the mean of each row of a matrix (★★☆)"></a>58. Subtract the mean of each row of a matrix (★★☆)</h4><blockquote><p>减去矩阵每一行的平均值</p></blockquote><p><code>hint: mean(axis=,keepdims=)</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Warren Weckesser</span></span><br><span class="line"></span><br><span class="line">X = np.random.rand(<span class="number">5</span>, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Recent versions of numpy</span></span><br><span class="line">Y = X - X.mean(axis=<span class="number">1</span>, keepdims=<span class="literal">True</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Older versions of numpy</span></span><br><span class="line">Y = X - X.mean(axis=<span class="number">1</span>).reshape(<span class="number">-1</span>, <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">print(Y)</span><br></pre></td></tr></table></figure><h4 id="59-How-to-sort-an-array-by-the-nth-column-★★☆"><a href="#59-How-to-sort-an-array-by-the-nth-column-★★☆" class="headerlink" title="59. How to sort an array by the nth column? (★★☆)"></a>59. How to sort an array by the nth column? (★★☆)</h4><blockquote><p>如何按第n列对数组排序</p></blockquote><p><code>hint: argsort</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Steve Tjoa</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,(<span class="number">3</span>,<span class="number">3</span>))</span><br><span class="line">print(Z)</span><br><span class="line">print(Z[Z[:,<span class="number">1</span>].argsort()])</span><br></pre></td></tr></table></figure><h4 id="60-How-to-tell-if-a-given-2D-array-has-null-columns-★★☆"><a href="#60-How-to-tell-if-a-given-2D-array-has-null-columns-★★☆" class="headerlink" title="60. How to tell if a given 2D array has null columns? (★★☆)"></a>60. How to tell if a given 2D array has null columns? (★★☆)</h4><blockquote><p>如何判断一个二维数组有全为0的列?</p></blockquote><p><code>hint: any, ~</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Warren Weckesser</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">3</span>,(<span class="number">3</span>,<span class="number">10</span>))</span><br><span class="line">print((~Z.any(axis=<span class="number">0</span>)).any())</span><br></pre></td></tr></table></figure><h4 id="61-Find-the-nearest-value-from-a-given-value-in-an-array-★★☆"><a href="#61-Find-the-nearest-value-from-a-given-value-in-an-array-★★☆" class="headerlink" title="61. Find the nearest value from a given value in an array (★★☆)"></a>61. Find the nearest value from a given value in an array (★★☆)</h4><blockquote><p>从数组中找出给定值的最近似值</p></blockquote><p><code>hint: np.abs, argmin, flat</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,<span class="number">10</span>)</span><br><span class="line">z = <span class="number">0.5</span></span><br><span class="line">m = Z.flat[np.abs(Z - z).argmin()]</span><br><span class="line">print(m)</span><br></pre></td></tr></table></figure><h4 id="62-Considering-two-arrays-with-shape-1-3-and-3-1-how-to-compute-their-sum-using-an-iterator-★★☆"><a href="#62-Considering-two-arrays-with-shape-1-3-and-3-1-how-to-compute-their-sum-using-an-iterator-★★☆" class="headerlink" title="62. Considering two arrays with shape (1,3) and (3,1), how to compute their sum using an iterator? (★★☆)"></a>62. Considering two arrays with shape (1,3) and (3,1), how to compute their sum using an iterator? (★★☆)</h4><blockquote><p>两个形状为(1,3)和(3,1)的数组,如何使用迭代器计算它们的总和</p></blockquote><p><code>hint: np.nditer</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">A = np.arange(<span class="number">3</span>).reshape(<span class="number">3</span>,<span class="number">1</span>)</span><br><span class="line">B = np.arange(<span class="number">3</span>).reshape(<span class="number">1</span>,<span class="number">3</span>)</span><br><span class="line">it = np.nditer([A,B,<span class="literal">None</span>])</span><br><span class="line"><span class="keyword">for</span> x,y,z <span class="keyword">in</span> it: z[...] = x + y</span><br><span class="line">print(it.operands[<span class="number">2</span>])</span><br></pre></td></tr></table></figure><h4 id="63-Create-an-array-class-that-has-a-name-attribute-★★☆"><a href="#63-Create-an-array-class-that-has-a-name-attribute-★★☆" class="headerlink" title="63. Create an array class that has a name attribute (★★☆)"></a>63. Create an array class that has a name attribute (★★☆)</h4><blockquote><p>创建一个有名字的数组类 </p></blockquote><p><code>hint: class method</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">NamedArray</span><span class="params">(np.ndarray)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__new__</span><span class="params">(cls, array, name=<span class="string">"no name"</span>)</span>:</span></span><br><span class="line"> obj = np.asarray(array).view(cls)</span><br><span class="line"> obj.name = name</span><br><span class="line"> <span class="keyword">return</span> obj</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__array_finalize__</span><span class="params">(self, obj)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> obj <span class="keyword">is</span> <span class="literal">None</span>: <span class="keyword">return</span></span><br><span class="line"> self.info = getattr(obj, <span class="string">'name'</span>, <span class="string">"no name"</span>)</span><br><span class="line"></span><br><span class="line">Z = NamedArray(np.arange(<span class="number">10</span>), <span class="string">"range_10"</span>)</span><br><span class="line"><span class="keyword">print</span> (Z.name)</span><br></pre></td></tr></table></figure><h4 id="64-Consider-a-given-vector-how-to-add-1-to-each-element-indexed-by-a-second-vector-be-careful-with-repeated-indices-★★★"><a href="#64-Consider-a-given-vector-how-to-add-1-to-each-element-indexed-by-a-second-vector-be-careful-with-repeated-indices-★★★" class="headerlink" title="64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)? (★★★)"></a>64. Consider a given vector, how to add 1 to each element indexed by a second vector (be careful with repeated indices)? (★★★)</h4><blockquote><p>考虑给定的向量,如何向由第二个向量索引的每个元素加1(小心重复索引)</p></blockquote><p><code>hint: np.bincount | np.add.at</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Brett Olsen</span></span><br><span class="line"></span><br><span class="line">Z = np.ones(<span class="number">10</span>)</span><br><span class="line">I = np.random.randint(<span class="number">0</span>,len(Z),<span class="number">20</span>)</span><br><span class="line">Z += np.bincount(I, minlength=len(Z))</span><br><span class="line">print(Z)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Another solution</span></span><br><span class="line"><span class="comment"># Author: Bartosz Telenczuk</span></span><br><span class="line">np.add.at(Z, I, <span class="number">1</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="65-How-to-accumulate-elements-of-a-vector-X-to-an-array-F-based-on-an-index-list-I-★★★"><a href="#65-How-to-accumulate-elements-of-a-vector-X-to-an-array-F-based-on-an-index-list-I-★★★" class="headerlink" title="65. How to accumulate elements of a vector (X) to an array (F) based on an index list (I)? (★★★)"></a>65. How to accumulate elements of a vector (X) to an array (F) based on an index list (I)? (★★★)</h4><blockquote><p>如何基于索引列表I,将向量X的各元素累加到数组F上</p></blockquote><p><code>hint: np.bincount</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Alan G Isaac</span></span><br><span class="line"></span><br><span class="line">X = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>,<span class="number">6</span>]</span><br><span class="line">I = [<span class="number">1</span>,<span class="number">3</span>,<span class="number">9</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">1</span>]</span><br><span class="line">F = np.bincount(I,X)</span><br><span class="line">print(F)</span><br></pre></td></tr></table></figure><h4 id="66-Considering-a-w-h-3-image-of-dtype-ubyte-compute-the-number-of-unique-colors-★★★"><a href="#66-Considering-a-w-h-3-image-of-dtype-ubyte-compute-the-number-of-unique-colors-★★★" class="headerlink" title="66. Considering a (w,h,3) image of (dtype=ubyte), compute the number of unique colors (★★★)"></a>66. Considering a (w,h,3) image of (dtype=ubyte), compute the number of unique colors (★★★)</h4><blockquote><p>考虑(dtype = ubyte)的(w,h,3)图像,计算唯一颜色的数量</p></blockquote><p><code>hint: np.unique</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Nadav Horesh</span></span><br><span class="line"></span><br><span class="line">w,h = <span class="number">16</span>,<span class="number">16</span></span><br><span class="line">I = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,(h,w,<span class="number">3</span>)).astype(np.ubyte)</span><br><span class="line">F = I[...,<span class="number">0</span>]*<span class="number">256</span>*<span class="number">256</span> + I[...,<span class="number">1</span>]*<span class="number">256</span> +I[...,<span class="number">2</span>]</span><br><span class="line">n = len(np.unique(F))</span><br><span class="line">print(np.unique(I))</span><br></pre></td></tr></table></figure><h4 id="67-Considering-a-four-dimensions-array-how-to-get-sum-over-the-last-two-axis-at-once-★★★"><a href="#67-Considering-a-four-dimensions-array-how-to-get-sum-over-the-last-two-axis-at-once-★★★" class="headerlink" title="67. Considering a four dimensions array, how to get sum over the last two axis at once? (★★★)"></a>67. Considering a four dimensions array, how to get sum over the last two axis at once? (★★★)</h4><blockquote><p>对一个四维数组,如何计算最后两个轴上的元素和?</p></blockquote><p><code>hint: sum(axis=(-2,-1))</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">A = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,(<span class="number">3</span>,<span class="number">4</span>,<span class="number">3</span>,<span class="number">4</span>))</span><br><span class="line"><span class="comment"># solution by passing a tuple of axes (introduced in numpy 1.7.0)</span></span><br><span class="line">sum = A.sum(axis=(<span class="number">-2</span>,<span class="number">-1</span>))</span><br><span class="line">print(sum)</span><br><span class="line"><span class="comment"># solution by flattening the last two dimensions into one</span></span><br><span class="line"><span class="comment"># (useful for functions that don't accept tuples for axis argument)</span></span><br><span class="line">sum = A.reshape(A.shape[:<span class="number">-2</span>] + (<span class="number">-1</span>,)).sum(axis=<span class="number">-1</span>)</span><br><span class="line">print(sum)</span><br></pre></td></tr></table></figure><h4 id="68-Considering-a-one-dimensional-vector-D-how-to-compute-means-of-subsets-of-D-using-a-vector-S-of-same-size-describing-subset-indices-★★★"><a href="#68-Considering-a-one-dimensional-vector-D-how-to-compute-means-of-subsets-of-D-using-a-vector-S-of-same-size-describing-subset-indices-★★★" class="headerlink" title="68. Considering a one-dimensional vector D, how to compute means of subsets of D using a vector S of same size describing subset indices? (★★★)"></a>68. Considering a one-dimensional vector D, how to compute means of subsets of D using a vector S of same size describing subset indices? (★★★)</h4><p>></p><p><code>hint: np.bincount</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jaime Fernández del Río</span></span><br><span class="line"></span><br><span class="line">D = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,<span class="number">100</span>)</span><br><span class="line">S = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,<span class="number">100</span>)</span><br><span class="line">D_sums = np.bincount(S, weights=D)</span><br><span class="line">D_counts = np.bincount(S)</span><br><span class="line">D_means = D_sums / D_counts</span><br><span class="line">print(D_means)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Pandas solution as a reference due to more intuitive code</span></span><br><span class="line"><span class="keyword">import</span> pandas <span class="keyword">as</span> pd</span><br><span class="line">print(pd.Series(D).groupby(S).mean())</span><br></pre></td></tr></table></figure><h4 id="69-How-to-get-the-diagonal-of-a-dot-product-★★★"><a href="#69-How-to-get-the-diagonal-of-a-dot-product-★★★" class="headerlink" title="69. How to get the diagonal of a dot product? (★★★)"></a>69. How to get the diagonal of a dot product? (★★★)</h4><blockquote><p>获取点积的对角矩阵?</p></blockquote><p><code>hint: np.diag</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Mathieu Blondel</span></span><br><span class="line"></span><br><span class="line">A = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,(<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line">B = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,(<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line"></span><br><span class="line"><span class="comment"># Slow version</span></span><br><span class="line">np.diag(np.dot(A, B))</span><br><span class="line"></span><br><span class="line"><span class="comment"># Fast version</span></span><br><span class="line">np.sum(A * B.T, axis=<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Faster version</span></span><br><span class="line">np.einsum(<span class="string">"ij,ji->i"</span>, A, B)</span><br></pre></td></tr></table></figure><h4 id="70-Consider-the-vector-1-2-3-4-5-how-to-build-a-new-vector-with-3-consecutive-zeros-interleaved-between-each-value-★★★"><a href="#70-Consider-the-vector-1-2-3-4-5-how-to-build-a-new-vector-with-3-consecutive-zeros-interleaved-between-each-value-★★★" class="headerlink" title="70. Consider the vector [1, 2, 3, 4, 5], how to build a new vector with 3 consecutive zeros interleaved between each value? (★★★)"></a>70. Consider the vector [1, 2, 3, 4, 5], how to build a new vector with 3 consecutive zeros interleaved between each value? (★★★)</h4><p>></p><p><code>hint: array[::4]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Warren Weckesser</span></span><br><span class="line"></span><br><span class="line">Z = np.array([<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>])</span><br><span class="line">nz = <span class="number">3</span></span><br><span class="line">Z0 = np.zeros(len(Z) + (len(Z)<span class="number">-1</span>)*(nz))</span><br><span class="line">Z0[::nz+<span class="number">1</span>] = Z</span><br><span class="line">print(Z0)</span><br></pre></td></tr></table></figure><h4 id="71-Consider-an-array-of-dimension-5-5-3-how-to-mulitply-it-by-an-array-with-dimensions-5-5-★★★"><a href="#71-Consider-an-array-of-dimension-5-5-3-how-to-mulitply-it-by-an-array-with-dimensions-5-5-★★★" class="headerlink" title="71. Consider an array of dimension (5,5,3), how to mulitply it by an array with dimensions (5,5)? (★★★)"></a>71. Consider an array of dimension (5,5,3), how to mulitply it by an array with dimensions (5,5)? (★★★)</h4><p>></p><p><code>hint: array[:, :, None]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">A = np.ones((<span class="number">5</span>,<span class="number">5</span>,<span class="number">3</span>))</span><br><span class="line">B = <span class="number">2</span>*np.ones((<span class="number">5</span>,<span class="number">5</span>))</span><br><span class="line">print(A * B[:,:,<span class="literal">None</span>])</span><br></pre></td></tr></table></figure><h4 id="72-How-to-swap-two-rows-of-an-array-★★★"><a href="#72-How-to-swap-two-rows-of-an-array-★★★" class="headerlink" title="72. How to swap two rows of an array? (★★★)"></a>72. How to swap two rows of an array? (★★★)</h4><p>></p><p><code>hint: array[[]] = array[[]]</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Eelco Hoogendoorn</span></span><br><span class="line"></span><br><span class="line">A = np.arange(<span class="number">25</span>).reshape(<span class="number">5</span>,<span class="number">5</span>)</span><br><span class="line">A[[<span class="number">0</span>,<span class="number">1</span>]] = A[[<span class="number">1</span>,<span class="number">0</span>]]</span><br><span class="line">print(A)</span><br></pre></td></tr></table></figure><h4 id="73-Consider-a-set-of-10-triplets-describing-10-triangles-with-shared-vertices-find-the-set-of-unique-line-segments-composing-all-the-triangles-★★★"><a href="#73-Consider-a-set-of-10-triplets-describing-10-triangles-with-shared-vertices-find-the-set-of-unique-line-segments-composing-all-the-triangles-★★★" class="headerlink" title="73. Consider a set of 10 triplets describing 10 triangles (with shared vertices), find the set of unique line segments composing all the triangles (★★★)"></a>73. Consider a set of 10 triplets describing 10 triangles (with shared vertices), find the set of unique line segments composing all the triangles (★★★)</h4><p>></p><p><code>hint: repeat, np.roll, np.sort, view, np.unique</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Nicolas P. Rougier</span></span><br><span class="line"></span><br><span class="line">faces = np.random.randint(<span class="number">0</span>,<span class="number">100</span>,(<span class="number">10</span>,<span class="number">3</span>))</span><br><span class="line">F = np.roll(faces.repeat(<span class="number">2</span>,axis=<span class="number">1</span>),<span class="number">-1</span>,axis=<span class="number">1</span>)</span><br><span class="line">F = F.reshape(len(F)*<span class="number">3</span>,<span class="number">2</span>)</span><br><span class="line">F = np.sort(F,axis=<span class="number">1</span>)</span><br><span class="line">G = F.view( dtype=[(<span class="string">'p0'</span>,F.dtype),(<span class="string">'p1'</span>,F.dtype)] )</span><br><span class="line">G = np.unique(G)</span><br><span class="line">print(G)</span><br></pre></td></tr></table></figure><h4 id="74-Given-an-array-C-that-is-a-bincount-how-to-produce-an-array-A-such-that-np-bincount-A-C-★★★"><a href="#74-Given-an-array-C-that-is-a-bincount-how-to-produce-an-array-A-such-that-np-bincount-A-C-★★★" class="headerlink" title="74. Given an array C that is a bincount, how to produce an array A such that np.bincount(A) == C? (★★★)"></a>74. Given an array C that is a bincount, how to produce an array A such that np.bincount(A) == C? (★★★)</h4><p>></p><p><code>hint: np.repeat</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jaime Fernández del Río</span></span><br><span class="line"></span><br><span class="line">C = np.bincount([<span class="number">1</span>,<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">4</span>,<span class="number">6</span>])</span><br><span class="line">A = np.repeat(np.arange(len(C)), C)</span><br><span class="line">print(A)</span><br></pre></td></tr></table></figure><h4 id="75-How-to-compute-averages-using-a-sliding-window-over-an-array-★★★"><a href="#75-How-to-compute-averages-using-a-sliding-window-over-an-array-★★★" class="headerlink" title="75. How to compute averages using a sliding window over an array? (★★★)"></a>75. How to compute averages using a sliding window over an array? (★★★)</h4><p>></p><p><code>hint: np.cumsum</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jaime Fernández del Río</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">moving_average</span><span class="params">(a, n=<span class="number">3</span>)</span> :</span></span><br><span class="line"> ret = np.cumsum(a, dtype=float)</span><br><span class="line"> ret[n:] = ret[n:] - ret[:-n]</span><br><span class="line"> <span class="keyword">return</span> ret[n - <span class="number">1</span>:] / n</span><br><span class="line">Z = np.arange(<span class="number">20</span>)</span><br><span class="line">print(moving_average(Z, n=<span class="number">3</span>))</span><br></pre></td></tr></table></figure><h4 id="76-Consider-a-one-dimensional-array-Z-build-a-two-dimensional-array-whose-first-row-is-Z-0-Z-1-Z-2-and-each-subsequent-row-is-shifted-by-1-last-row-should-be-Z-3-Z-2-Z-1-★★★"><a href="#76-Consider-a-one-dimensional-array-Z-build-a-two-dimensional-array-whose-first-row-is-Z-0-Z-1-Z-2-and-each-subsequent-row-is-shifted-by-1-last-row-should-be-Z-3-Z-2-Z-1-★★★" class="headerlink" title="76. Consider a one-dimensional array Z, build a two-dimensional array whose first row is (Z[0],Z[1],Z[2]) and each subsequent row is shifted by 1 (last row should be (Z[-3],Z[-2],Z[-1]) (★★★)"></a>76. Consider a one-dimensional array Z, build a two-dimensional array whose first row is (Z[0],Z[1],Z[2]) and each subsequent row is shifted by 1 (last row should be (Z[-3],Z[-2],Z[-1]) (★★★)</h4><p>></p><p><code>hint: from numpy.lib import stride_tricks</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Joe Kington / Erik Rigtorp</span></span><br><span class="line"><span class="keyword">from</span> numpy.lib <span class="keyword">import</span> stride_tricks</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">rolling</span><span class="params">(a, window)</span>:</span></span><br><span class="line"> shape = (a.size - window + <span class="number">1</span>, window)</span><br><span class="line"> strides = (a.itemsize, a.itemsize)</span><br><span class="line"> <span class="keyword">return</span> stride_tricks.as_strided(a, shape=shape, strides=strides)</span><br><span class="line">Z = rolling(np.arange(<span class="number">10</span>), <span class="number">3</span>)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="77-How-to-negate-a-boolean-or-to-change-the-sign-of-a-float-inplace-★★★"><a href="#77-How-to-negate-a-boolean-or-to-change-the-sign-of-a-float-inplace-★★★" class="headerlink" title="77. How to negate a boolean, or to change the sign of a float inplace? (★★★)"></a>77. How to negate a boolean, or to change the sign of a float inplace? (★★★)</h4><p>></p><p><code>hint: np.logical_not, np.negative</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Nathaniel J. Smith</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,<span class="number">100</span>)</span><br><span class="line">np.logical_not(Z, out=Z)</span><br><span class="line"></span><br><span class="line">Z = np.random.uniform(<span class="number">-1.0</span>,<span class="number">1.0</span>,<span class="number">100</span>)</span><br><span class="line">np.negative(Z, out=Z)</span><br></pre></td></tr></table></figure><h4 id="78-Consider-2-sets-of-points-P0-P1-describing-lines-2d-and-a-point-p-how-to-compute-distance-from-p-to-each-line-i-P0-i-P1-i-★★★"><a href="#78-Consider-2-sets-of-points-P0-P1-describing-lines-2d-and-a-point-p-how-to-compute-distance-from-p-to-each-line-i-P0-i-P1-i-★★★" class="headerlink" title="78. Consider 2 sets of points P0,P1 describing lines (2d) and a point p, how to compute distance from p to each line i (P0[i],P1[i])? (★★★)"></a>78. Consider 2 sets of points P0,P1 describing lines (2d) and a point p, how to compute distance from p to each line i (P0[i],P1[i])? (★★★)</h4><p>></p><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">distance</span><span class="params">(P0, P1, p)</span>:</span></span><br><span class="line"> T = P1 - P0</span><br><span class="line"> L = (T**<span class="number">2</span>).sum(axis=<span class="number">1</span>)</span><br><span class="line"> U = -((P0[:,<span class="number">0</span>]-p[...,<span class="number">0</span>])*T[:,<span class="number">0</span>] + (P0[:,<span class="number">1</span>]-p[...,<span class="number">1</span>])*T[:,<span class="number">1</span>]) / L</span><br><span class="line"> U = U.reshape(len(U),<span class="number">1</span>)</span><br><span class="line"> D = P0 + U*T - p</span><br><span class="line"> <span class="keyword">return</span> np.sqrt((D**<span class="number">2</span>).sum(axis=<span class="number">1</span>))</span><br><span class="line"></span><br><span class="line">P0 = np.random.uniform(<span class="number">-10</span>,<span class="number">10</span>,(<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">P1 = np.random.uniform(<span class="number">-10</span>,<span class="number">10</span>,(<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">p = np.random.uniform(<span class="number">-10</span>,<span class="number">10</span>,( <span class="number">1</span>,<span class="number">2</span>))</span><br><span class="line">print(distance(P0, P1, p))</span><br></pre></td></tr></table></figure><h4 id="79-Consider-2-sets-of-points-P0-P1-describing-lines-2d-and-a-set-of-points-P-how-to-compute-distance-from-each-point-j-P-j-to-each-line-i-P0-i-P1-i-★★★"><a href="#79-Consider-2-sets-of-points-P0-P1-describing-lines-2d-and-a-set-of-points-P-how-to-compute-distance-from-each-point-j-P-j-to-each-line-i-P0-i-P1-i-★★★" class="headerlink" title="79. Consider 2 sets of points P0,P1 describing lines (2d) and a set of points P, how to compute distance from each point j (P[j]) to each line i (P0[i],P1[i])? (★★★)"></a>79. Consider 2 sets of points P0,P1 describing lines (2d) and a set of points P, how to compute distance from each point j (P[j]) to each line i (P0[i],P1[i])? (★★★)</h4><p>></p><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Italmassov Kuanysh</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># based on distance function from previous question</span></span><br><span class="line">P0 = np.random.uniform(<span class="number">-10</span>, <span class="number">10</span>, (<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">P1 = np.random.uniform(<span class="number">-10</span>,<span class="number">10</span>,(<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">p = np.random.uniform(<span class="number">-10</span>, <span class="number">10</span>, (<span class="number">10</span>,<span class="number">2</span>))</span><br><span class="line">print(np.array([distance(P0,P1,p_i) <span class="keyword">for</span> p_i <span class="keyword">in</span> p]))</span><br></pre></td></tr></table></figure><h4 id="80-Consider-an-arbitrary-array-write-a-function-that-extract-a-subpart-with-a-fixed-shape-and-centered-on-a-given-element-pad-with-a-fill-value-when-necessary-★★★"><a href="#80-Consider-an-arbitrary-array-write-a-function-that-extract-a-subpart-with-a-fixed-shape-and-centered-on-a-given-element-pad-with-a-fill-value-when-necessary-★★★" class="headerlink" title="80. Consider an arbitrary array, write a function that extract a subpart with a fixed shape and centered on a given element (pad with a fill value when necessary) (★★★)"></a>80. Consider an arbitrary array, write a function that extract a subpart with a fixed shape and centered on a given element (pad with a <code>fill</code> value when necessary) (★★★)</h4><p>></p><p><code>hint: minimum maximum</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Nicolas Rougier</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,(<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">shape = (<span class="number">5</span>,<span class="number">5</span>)</span><br><span class="line">fill = <span class="number">0</span></span><br><span class="line">position = (<span class="number">1</span>,<span class="number">1</span>)</span><br><span class="line"></span><br><span class="line">R = np.ones(shape, dtype=Z.dtype)*fill</span><br><span class="line">P = np.array(list(position)).astype(int)</span><br><span class="line">Rs = np.array(list(R.shape)).astype(int)</span><br><span class="line">Zs = np.array(list(Z.shape)).astype(int)</span><br><span class="line"></span><br><span class="line">R_start = np.zeros((len(shape),)).astype(int)</span><br><span class="line">R_stop = np.array(list(shape)).astype(int)</span><br><span class="line">Z_start = (P-Rs//<span class="number">2</span>)</span><br><span class="line">Z_stop = (P+Rs//<span class="number">2</span>)+Rs%<span class="number">2</span></span><br><span class="line"></span><br><span class="line">R_start = (R_start - np.minimum(Z_start,<span class="number">0</span>)).tolist()</span><br><span class="line">Z_start = (np.maximum(Z_start,<span class="number">0</span>)).tolist()</span><br><span class="line">R_stop = np.maximum(R_start, (R_stop - np.maximum(Z_stop-Zs,<span class="number">0</span>))).tolist()</span><br><span class="line">Z_stop = (np.minimum(Z_stop,Zs)).tolist()</span><br><span class="line"></span><br><span class="line">r = [slice(start,stop) <span class="keyword">for</span> start,stop <span class="keyword">in</span> zip(R_start,R_stop)]</span><br><span class="line">z = [slice(start,stop) <span class="keyword">for</span> start,stop <span class="keyword">in</span> zip(Z_start,Z_stop)]</span><br><span class="line">R[r] = Z[z]</span><br><span class="line">print(Z)</span><br><span class="line">print(R)</span><br></pre></td></tr></table></figure><h4 id="81-Consider-an-array-Z-1-2-3-4-5-6-7-8-9-10-11-12-13-14-how-to-generate-an-array-R-1-2-3-4-2-3-4-5-3-4-5-6-…-11-12-13-14-★★★"><a href="#81-Consider-an-array-Z-1-2-3-4-5-6-7-8-9-10-11-12-13-14-how-to-generate-an-array-R-1-2-3-4-2-3-4-5-3-4-5-6-…-11-12-13-14-★★★" class="headerlink" title="81. Consider an array Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14], how to generate an array R = [[1,2,3,4], [2,3,4,5], [3,4,5,6], …, [11,12,13,14]]? (★★★)"></a>81. Consider an array Z = [1,2,3,4,5,6,7,8,9,10,11,12,13,14], how to generate an array R = [[1,2,3,4], [2,3,4,5], [3,4,5,6], …, [11,12,13,14]]? (★★★)</h4><p>></p><p><code>hint: stride_tricks.as_strided</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Stefan van der Walt</span></span><br><span class="line"></span><br><span class="line">Z = np.arange(<span class="number">1</span>,<span class="number">15</span>,dtype=np.uint32)</span><br><span class="line">R = stride_tricks.as_strided(Z,(<span class="number">11</span>,<span class="number">4</span>),(<span class="number">4</span>,<span class="number">4</span>))</span><br><span class="line">print(R)</span><br></pre></td></tr></table></figure><h4 id="82-Compute-a-matrix-rank-★★★"><a href="#82-Compute-a-matrix-rank-★★★" class="headerlink" title="82. Compute a matrix rank (★★★)"></a>82. Compute a matrix rank (★★★)</h4><p>></p><p><code>hint: np.linalg.svd</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Stefan van der Walt</span></span><br><span class="line"></span><br><span class="line">Z = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,(<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">U, S, V = np.linalg.svd(Z) <span class="comment"># Singular Value Decomposition</span></span><br><span class="line">rank = np.sum(S > <span class="number">1e-10</span>)</span><br><span class="line"></span><br><span class="line">print(rank)</span><br></pre></td></tr></table></figure><h4 id="83-How-to-find-the-most-frequent-value-in-an-array"><a href="#83-How-to-find-the-most-frequent-value-in-an-array" class="headerlink" title="83. How to find the most frequent value in an array?"></a>83. How to find the most frequent value in an array?</h4><p>></p><p><code>hint: np.bincount, argmax</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">10</span>,<span class="number">50</span>)</span><br><span class="line">print(np.bincount(Z).argmax())</span><br></pre></td></tr></table></figure><h4 id="84-Extract-all-the-contiguous-3x3-blocks-from-a-random-10x10-matrix-★★★"><a href="#84-Extract-all-the-contiguous-3x3-blocks-from-a-random-10x10-matrix-★★★" class="headerlink" title="84. Extract all the contiguous 3x3 blocks from a random 10x10 matrix (★★★)"></a>84. Extract all the contiguous 3x3 blocks from a random 10x10 matrix (★★★)</h4><p>></p><p><code>hint: stride_tricks.as_strided</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Chris Barker</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">5</span>,(<span class="number">10</span>,<span class="number">10</span>))</span><br><span class="line">n = <span class="number">3</span></span><br><span class="line">i = <span class="number">1</span> + (Z.shape[<span class="number">0</span>]<span class="number">-3</span>)</span><br><span class="line">j = <span class="number">1</span> + (Z.shape[<span class="number">1</span>]<span class="number">-3</span>)</span><br><span class="line">C = stride_tricks.as_strided(Z, shape=(i, j, n, n), strides=Z.strides + Z.strides)</span><br><span class="line">print(C)</span><br></pre></td></tr></table></figure><h4 id="85-Create-a-2D-array-subclass-such-that-Z-i-j-Z-j-i-★★★"><a href="#85-Create-a-2D-array-subclass-such-that-Z-i-j-Z-j-i-★★★" class="headerlink" title="85. Create a 2D array subclass such that Z[i,j] == Z[j,i] (★★★)"></a>85. Create a 2D array subclass such that Z[i,j] == Z[j,i] (★★★)</h4><p>></p><p><code>hint: class method</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Eric O. Lebigot</span></span><br><span class="line"><span class="comment"># Note: only works for 2d array and value setting using indices</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Symetric</span><span class="params">(np.ndarray)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setitem__</span><span class="params">(self, index, value)</span>:</span></span><br><span class="line"> i,j = index</span><br><span class="line"> super(Symetric, self).__setitem__((i,j), value)</span><br><span class="line"> super(Symetric, self).__setitem__((j,i), value)</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">symetric</span><span class="params">(Z)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> np.asarray(Z + Z.T - np.diag(Z.diagonal())).view(Symetric)</span><br><span class="line"></span><br><span class="line">S = symetric(np.random.randint(<span class="number">0</span>,<span class="number">10</span>,(<span class="number">5</span>,<span class="number">5</span>)))</span><br><span class="line">S[<span class="number">2</span>,<span class="number">3</span>] = <span class="number">42</span></span><br><span class="line">print(S)</span><br></pre></td></tr></table></figure><h4 id="86-Consider-a-set-of-p-matrices-wich-shape-n-n-and-a-set-of-p-vectors-with-shape-n-1-How-to-compute-the-sum-of-of-the-p-matrix-products-at-once-result-has-shape-n-1-★★★"><a href="#86-Consider-a-set-of-p-matrices-wich-shape-n-n-and-a-set-of-p-vectors-with-shape-n-1-How-to-compute-the-sum-of-of-the-p-matrix-products-at-once-result-has-shape-n-1-★★★" class="headerlink" title="86. Consider a set of p matrices wich shape (n,n) and a set of p vectors with shape (n,1). How to compute the sum of of the p matrix products at once? (result has shape (n,1)) (★★★)"></a>86. Consider a set of p matrices wich shape (n,n) and a set of p vectors with shape (n,1). How to compute the sum of of the p matrix products at once? (result has shape (n,1)) (★★★)</h4><p>></p><p><code>hint: np.tensordot</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Stefan van der Walt</span></span><br><span class="line"></span><br><span class="line">p, n = <span class="number">10</span>, <span class="number">20</span></span><br><span class="line">M = np.ones((p,n,n))</span><br><span class="line">V = np.ones((p,n,<span class="number">1</span>))</span><br><span class="line">S = np.tensordot(M, V, axes=[[<span class="number">0</span>, <span class="number">2</span>], [<span class="number">0</span>, <span class="number">1</span>]])</span><br><span class="line">print(S)</span><br><span class="line"></span><br><span class="line"><span class="comment"># It works, because:</span></span><br><span class="line"><span class="comment"># M is (p,n,n)</span></span><br><span class="line"><span class="comment"># V is (p,n,1)</span></span><br><span class="line"><span class="comment"># Thus, summing over the paired axes 0 and 0 (of M and V independently),</span></span><br><span class="line"><span class="comment"># and 2 and 1, to remain with a (n,1) vector.</span></span><br></pre></td></tr></table></figure><h4 id="87-Consider-a-16x16-array-how-to-get-the-block-sum-block-size-is-4x4-★★★"><a href="#87-Consider-a-16x16-array-how-to-get-the-block-sum-block-size-is-4x4-★★★" class="headerlink" title="87. Consider a 16x16 array, how to get the block-sum (block size is 4x4)? (★★★)"></a>87. Consider a 16x16 array, how to get the block-sum (block size is 4x4)? (★★★)</h4><p>></p><p><code>hint: np.add.reduceat</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Robert Kern</span></span><br><span class="line"></span><br><span class="line">Z = np.ones((<span class="number">16</span>,<span class="number">16</span>))</span><br><span class="line">k = <span class="number">4</span></span><br><span class="line">S = np.add.reduceat(np.add.reduceat(Z, np.arange(<span class="number">0</span>, Z.shape[<span class="number">0</span>], k), axis=<span class="number">0</span>),</span><br><span class="line"> np.arange(<span class="number">0</span>, Z.shape[<span class="number">1</span>], k), axis=<span class="number">1</span>)</span><br><span class="line">print(S)</span><br></pre></td></tr></table></figure><h4 id="88-How-to-implement-the-Game-of-Life-using-numpy-arrays-★★★"><a href="#88-How-to-implement-the-Game-of-Life-using-numpy-arrays-★★★" class="headerlink" title="88. How to implement the Game of Life using numpy arrays? (★★★)"></a>88. How to implement the Game of Life using numpy arrays? (★★★)</h4><p>></p><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Nicolas Rougier</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">iterate</span><span class="params">(Z)</span>:</span></span><br><span class="line"> <span class="comment"># Count neighbours</span></span><br><span class="line"> N = (Z[<span class="number">0</span>:<span class="number">-2</span>,<span class="number">0</span>:<span class="number">-2</span>] + Z[<span class="number">0</span>:<span class="number">-2</span>,<span class="number">1</span>:<span class="number">-1</span>] + Z[<span class="number">0</span>:<span class="number">-2</span>,<span class="number">2</span>:] +</span><br><span class="line"> Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">0</span>:<span class="number">-2</span>] + Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">2</span>:] +</span><br><span class="line"> Z[<span class="number">2</span>: ,<span class="number">0</span>:<span class="number">-2</span>] + Z[<span class="number">2</span>: ,<span class="number">1</span>:<span class="number">-1</span>] + Z[<span class="number">2</span>: ,<span class="number">2</span>:])</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Apply rules</span></span><br><span class="line"> birth = (N==<span class="number">3</span>) & (Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">1</span>:<span class="number">-1</span>]==<span class="number">0</span>)</span><br><span class="line"> survive = ((N==<span class="number">2</span>) | (N==<span class="number">3</span>)) & (Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">1</span>:<span class="number">-1</span>]==<span class="number">1</span>)</span><br><span class="line"> Z[...] = <span class="number">0</span></span><br><span class="line"> Z[<span class="number">1</span>:<span class="number">-1</span>,<span class="number">1</span>:<span class="number">-1</span>][birth | survive] = <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> Z</span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,(<span class="number">50</span>,<span class="number">50</span>))</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">100</span>): Z = iterate(Z)</span><br><span class="line">print(Z)</span><br></pre></td></tr></table></figure><h4 id="89-How-to-get-the-n-largest-values-of-an-array-★★★"><a href="#89-How-to-get-the-n-largest-values-of-an-array-★★★" class="headerlink" title="89. How to get the n largest values of an array (★★★)"></a>89. How to get the n largest values of an array (★★★)</h4><p>></p><p><code>hint: np.argsort | np.argpartition</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Z = np.arange(<span class="number">10000</span>)</span><br><span class="line">np.random.shuffle(Z)</span><br><span class="line">n = <span class="number">5</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Slow</span></span><br><span class="line"><span class="keyword">print</span> (Z[np.argsort(Z)[-n:]])</span><br><span class="line"></span><br><span class="line"><span class="comment"># Fast</span></span><br><span class="line"><span class="keyword">print</span> (Z[np.argpartition(-Z,n)[:n]])</span><br></pre></td></tr></table></figure><h4 id="90-Given-an-arbitrary-number-of-vectors-build-the-cartesian-product-every-combinations-of-every-item-★★★"><a href="#90-Given-an-arbitrary-number-of-vectors-build-the-cartesian-product-every-combinations-of-every-item-★★★" class="headerlink" title="90. Given an arbitrary number of vectors, build the cartesian product (every combinations of every item) (★★★)"></a>90. Given an arbitrary number of vectors, build the cartesian product (every combinations of every item) (★★★)</h4><p>></p><p><code>hint: np.indices</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Stefan Van der Walt</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">cartesian</span><span class="params">(arrays)</span>:</span></span><br><span class="line"> arrays = [np.asarray(a) <span class="keyword">for</span> a <span class="keyword">in</span> arrays]</span><br><span class="line"> shape = (len(x) <span class="keyword">for</span> x <span class="keyword">in</span> arrays)</span><br><span class="line"></span><br><span class="line"> ix = np.indices(shape, dtype=int)</span><br><span class="line"> ix = ix.reshape(len(arrays), <span class="number">-1</span>).T</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> n, arr <span class="keyword">in</span> enumerate(arrays):</span><br><span class="line"> ix[:, n] = arrays[n][ix[:, n]]</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ix</span><br><span class="line"></span><br><span class="line"><span class="keyword">print</span> (cartesian(([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>], [<span class="number">4</span>, <span class="number">5</span>], [<span class="number">6</span>, <span class="number">7</span>])))</span><br></pre></td></tr></table></figure><h4 id="91-How-to-create-a-record-array-from-a-regular-array-★★★"><a href="#91-How-to-create-a-record-array-from-a-regular-array-★★★" class="headerlink" title="91. How to create a record array from a regular array? (★★★)"></a>91. How to create a record array from a regular array? (★★★)</h4><p>></p><p><code>hint: np.core.records.fromarrays</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Z = np.array([(<span class="string">"Hello"</span>, <span class="number">2.5</span>, <span class="number">3</span>),</span><br><span class="line"> (<span class="string">"World"</span>, <span class="number">3.6</span>, <span class="number">2</span>)])</span><br><span class="line">R = np.core.records.fromarrays(Z.T,</span><br><span class="line"> names=<span class="string">'col1, col2, col3'</span>,</span><br><span class="line"> formats = <span class="string">'S8, f8, i8'</span>)</span><br><span class="line">print(R)</span><br></pre></td></tr></table></figure><h4 id="92-Consider-a-large-vector-Z-compute-Z-to-the-power-of-3-using-3-different-methods-★★★"><a href="#92-Consider-a-large-vector-Z-compute-Z-to-the-power-of-3-using-3-different-methods-★★★" class="headerlink" title="92. Consider a large vector Z, compute Z to the power of 3 using 3 different methods (★★★)"></a>92. Consider a large vector Z, compute Z to the power of 3 using 3 different methods (★★★)</h4><p>></p><p><code>hint: np.power, *, np.einsum</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Ryan G.</span></span><br><span class="line"></span><br><span class="line">x = np.random.rand(int(<span class="number">5e7</span>))</span><br><span class="line"></span><br><span class="line">%timeit np.power(x,<span class="number">3</span>)</span><br><span class="line">%timeit x*x*x</span><br><span class="line">%timeit np.einsum(<span class="string">'i,i,i->i'</span>,x,x,x)</span><br></pre></td></tr></table></figure><h4 id="93-Consider-two-arrays-A-and-B-of-shape-8-3-and-2-2-How-to-find-rows-of-A-that-contain-elements-of-each-row-of-B-regardless-of-the-order-of-the-elements-in-B-★★★"><a href="#93-Consider-two-arrays-A-and-B-of-shape-8-3-and-2-2-How-to-find-rows-of-A-that-contain-elements-of-each-row-of-B-regardless-of-the-order-of-the-elements-in-B-★★★" class="headerlink" title="93. Consider two arrays A and B of shape (8,3) and (2,2). How to find rows of A that contain elements of each row of B regardless of the order of the elements in B? (★★★)"></a>93. Consider two arrays A and B of shape (8,3) and (2,2). How to find rows of A that contain elements of each row of B regardless of the order of the elements in B? (★★★)</h4><p>></p><p><code>hint: np.where</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Gabe Schwartz</span></span><br><span class="line"></span><br><span class="line">A = np.random.randint(<span class="number">0</span>,<span class="number">5</span>,(<span class="number">8</span>,<span class="number">3</span>))</span><br><span class="line">B = np.random.randint(<span class="number">0</span>,<span class="number">5</span>,(<span class="number">2</span>,<span class="number">2</span>))</span><br><span class="line"></span><br><span class="line">C = (A[..., np.newaxis, np.newaxis] == B)</span><br><span class="line">rows = np.where(C.any((<span class="number">3</span>,<span class="number">1</span>)).all(<span class="number">1</span>))[<span class="number">0</span>]</span><br><span class="line">print(rows)</span><br></pre></td></tr></table></figure><h4 id="94-Considering-a-10x3-matrix-extract-rows-with-unequal-values-e-g-2-2-3-★★★"><a href="#94-Considering-a-10x3-matrix-extract-rows-with-unequal-values-e-g-2-2-3-★★★" class="headerlink" title="94. Considering a 10x3 matrix, extract rows with unequal values (e.g. [2,2,3]) (★★★)"></a>94. Considering a 10x3 matrix, extract rows with unequal values (e.g. [2,2,3]) (★★★)</h4><p>></p><p><code>No hints provided...</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Robert Kern</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">5</span>,(<span class="number">10</span>,<span class="number">3</span>))</span><br><span class="line">print(Z)</span><br><span class="line"><span class="comment"># solution for arrays of all dtypes (including string arrays and record arrays)</span></span><br><span class="line">E = np.all(Z[:,<span class="number">1</span>:] == Z[:,:<span class="number">-1</span>], axis=<span class="number">1</span>)</span><br><span class="line">U = Z[~E]</span><br><span class="line">print(U)</span><br><span class="line"><span class="comment"># soluiton for numerical arrays only, will work for any number of columns in Z</span></span><br><span class="line">U = Z[Z.max(axis=<span class="number">1</span>) != Z.min(axis=<span class="number">1</span>),:]</span><br><span class="line">print(U)</span><br></pre></td></tr></table></figure><h4 id="95-Convert-a-vector-of-ints-into-a-matrix-binary-representation-★★★"><a href="#95-Convert-a-vector-of-ints-into-a-matrix-binary-representation-★★★" class="headerlink" title="95. Convert a vector of ints into a matrix binary representation (★★★)"></a>95. Convert a vector of ints into a matrix binary representation (★★★)</h4><p>></p><p><code>hint: np.unpackbits</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Warren Weckesser</span></span><br><span class="line"></span><br><span class="line">I = np.array([<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">15</span>, <span class="number">16</span>, <span class="number">32</span>, <span class="number">64</span>, <span class="number">128</span>])</span><br><span class="line">B = ((I.reshape(<span class="number">-1</span>,<span class="number">1</span>) & (<span class="number">2</span>**np.arange(<span class="number">8</span>))) != <span class="number">0</span>).astype(int)</span><br><span class="line">print(B[:,::<span class="number">-1</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment"># Author: Daniel T. McDonald</span></span><br><span class="line"></span><br><span class="line">I = np.array([<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">15</span>, <span class="number">16</span>, <span class="number">32</span>, <span class="number">64</span>, <span class="number">128</span>], dtype=np.uint8)</span><br><span class="line">print(np.unpackbits(I[:, np.newaxis], axis=<span class="number">1</span>))</span><br></pre></td></tr></table></figure><h4 id="96-Given-a-two-dimensional-array-how-to-extract-unique-rows-★★★"><a href="#96-Given-a-two-dimensional-array-how-to-extract-unique-rows-★★★" class="headerlink" title="96. Given a two dimensional array, how to extract unique rows? (★★★)"></a>96. Given a two dimensional array, how to extract unique rows? (★★★)</h4><blockquote><p>从二维矩阵中找出不同的行?</p></blockquote><p><code>hint: np.ascontiguousarray | np.unique</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jaime Fernández del Río</span></span><br><span class="line"></span><br><span class="line">Z = np.random.randint(<span class="number">0</span>,<span class="number">2</span>,(<span class="number">6</span>,<span class="number">3</span>))</span><br><span class="line">T = np.ascontiguousarray(Z).view(np.dtype((np.void, Z.dtype.itemsize * Z.shape[<span class="number">1</span>])))</span><br><span class="line">_, idx = np.unique(T, return_index=<span class="literal">True</span>)</span><br><span class="line">uZ = Z[idx]</span><br><span class="line">print(uZ)</span><br><span class="line"></span><br><span class="line"><span class="comment"># Author: Andreas Kouzelis</span></span><br><span class="line"><span class="comment"># NumPy >= 1.13</span></span><br><span class="line">uZ = np.unique(Z, axis=<span class="number">0</span>)</span><br><span class="line">print(uZ)</span><br></pre></td></tr></table></figure><h4 id="97-Considering-2-vectors-A-amp-B-write-the-einsum-equivalent-of-inner-outer-sum-and-mul-function-★★★"><a href="#97-Considering-2-vectors-A-amp-B-write-the-einsum-equivalent-of-inner-outer-sum-and-mul-function-★★★" class="headerlink" title="97. Considering 2 vectors A & B, write the einsum equivalent of inner, outer, sum, and mul function (★★★)"></a>97. Considering 2 vectors A & B, write the einsum equivalent of inner, outer, sum, and mul function (★★★)</h4><blockquote><p>给定数组A,B,使用函数einsum实现求和,矩阵相乘,内积和外积</p></blockquote><p><code>hint: np.einsum</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Alex Riley</span></span><br><span class="line"><span class="comment"># Make sure to read: http://ajcr.net/Basic-guide-to-einsum/</span></span><br><span class="line"></span><br><span class="line">A = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,<span class="number">10</span>)</span><br><span class="line">B = np.random.uniform(<span class="number">0</span>,<span class="number">1</span>,<span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">np.einsum(<span class="string">'i->'</span>, A) <span class="comment"># np.sum(A)</span></span><br><span class="line">np.einsum(<span class="string">'i,i->i'</span>, A, B) <span class="comment"># A * B</span></span><br><span class="line">np.einsum(<span class="string">'i,i'</span>, A, B) <span class="comment"># np.inner(A, B)</span></span><br><span class="line">np.einsum(<span class="string">'i,j->ij'</span>, A, B) <span class="comment"># np.outer(A, B)</span></span><br></pre></td></tr></table></figure><h4 id="98-Considering-a-path-described-by-two-vectors-X-Y-how-to-sample-it-using-equidistant-samples-★★★"><a href="#98-Considering-a-path-described-by-two-vectors-X-Y-how-to-sample-it-using-equidistant-samples-★★★" class="headerlink" title="98. Considering a path described by two vectors (X,Y), how to sample it using equidistant samples (★★★)?"></a>98. Considering a path described by two vectors (X,Y), how to sample it using equidistant samples (★★★)?</h4><blockquote><p>给定用两组向量(X,Y)描述的一条线,如何进行等距采样</p></blockquote><p><code>hint: np.cumsum, np.interp</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Bas Swinckels</span></span><br><span class="line"></span><br><span class="line">phi = np.arange(<span class="number">0</span>, <span class="number">10</span>*np.pi, <span class="number">0.1</span>)</span><br><span class="line">a = <span class="number">1</span></span><br><span class="line">x = a*phi*np.cos(phi)</span><br><span class="line">y = a*phi*np.sin(phi)</span><br><span class="line"></span><br><span class="line">dr = (np.diff(x)**<span class="number">2</span> + np.diff(y)**<span class="number">2</span>)**<span class="number">.5</span> <span class="comment"># segment lengths</span></span><br><span class="line">r = np.zeros_like(x)</span><br><span class="line">r[<span class="number">1</span>:] = np.cumsum(dr) <span class="comment"># integrate path</span></span><br><span class="line">r_int = np.linspace(<span class="number">0</span>, r.max(), <span class="number">200</span>) <span class="comment"># regular spaced path</span></span><br><span class="line">x_int = np.interp(r_int, r, x) <span class="comment"># integrate path</span></span><br><span class="line">y_int = np.interp(r_int, r, y)</span><br></pre></td></tr></table></figure><h4 id="99-Given-an-integer-n-and-a-2D-array-X-select-from-X-the-rows-which-can-be-interpreted-as-draws-from-a-multinomial-distribution-with-n-degrees-i-e-the-rows-which-only-contain-integers-and-which-sum-to-n-★★★"><a href="#99-Given-an-integer-n-and-a-2D-array-X-select-from-X-the-rows-which-can-be-interpreted-as-draws-from-a-multinomial-distribution-with-n-degrees-i-e-the-rows-which-only-contain-integers-and-which-sum-to-n-★★★" class="headerlink" title="99. Given an integer n and a 2D array X, select from X the rows which can be interpreted as draws from a multinomial distribution with n degrees, i.e., the rows which only contain integers and which sum to n. (★★★)"></a>99. Given an integer n and a 2D array X, select from X the rows which can be interpreted as draws from a multinomial distribution with n degrees, i.e., the rows which only contain integers and which sum to n. (★★★)</h4><blockquote><p>给定整数n和一个二维数组X,从X中找出满足条件的行 指数为n的多项式分布</p></blockquote><p><code>hint: np.logical_and.reduce, np.mod</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Evgeni Burovski</span></span><br><span class="line"></span><br><span class="line">X = np.asarray([[<span class="number">1.0</span>, <span class="number">0.0</span>, <span class="number">3.0</span>, <span class="number">8.0</span>],</span><br><span class="line"> [<span class="number">2.0</span>, <span class="number">0.0</span>, <span class="number">1.0</span>, <span class="number">1.0</span>],</span><br><span class="line"> [<span class="number">1.5</span>, <span class="number">2.5</span>, <span class="number">1.0</span>, <span class="number">0.0</span>]])</span><br><span class="line">n = <span class="number">4</span></span><br><span class="line">M = np.logical_and.reduce(np.mod(X, <span class="number">1</span>) == <span class="number">0</span>, axis=<span class="number">-1</span>)</span><br><span class="line">M &= (X.sum(axis=<span class="number">-1</span>) == n)</span><br><span class="line">print(X[M])</span><br></pre></td></tr></table></figure><h4 id="100-Compute-bootstrapped-95-confidence-intervals-for-the-mean-of-a-1D-array-X-i-e-resample-the-elements-of-an-array-with-replacement-N-times-compute-the-mean-of-each-sample-and-then-compute-percentiles-over-the-means-★★★"><a href="#100-Compute-bootstrapped-95-confidence-intervals-for-the-mean-of-a-1D-array-X-i-e-resample-the-elements-of-an-array-with-replacement-N-times-compute-the-mean-of-each-sample-and-then-compute-percentiles-over-the-means-★★★" class="headerlink" title="100. Compute bootstrapped 95% confidence intervals for the mean of a 1D array X (i.e., resample the elements of an array with replacement N times, compute the mean of each sample, and then compute percentiles over the means). (★★★)"></a>100. Compute bootstrapped 95% confidence intervals for the mean of a 1D array X (i.e., resample the elements of an array with replacement N times, compute the mean of each sample, and then compute percentiles over the means). (★★★)</h4><blockquote><p>为一维数组X的平均值计算自举的95%置信区间(即,用替换N次对数组的元素进行重新采样,计算每个样本的平均值,然后计算平均值的百分位数</p></blockquote><p><code>hint: np.percentile</code></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Author: Jessica B. Hamrick</span></span><br><span class="line"></span><br><span class="line">X = np.random.randn(<span class="number">100</span>) <span class="comment"># random 1D array</span></span><br><span class="line">N = <span class="number">1000</span> <span class="comment"># number of bootstrap samples</span></span><br><span class="line">idx = np.random.randint(<span class="number">0</span>, X.size, (N, X.size))</span><br><span class="line">means = X[idx].mean(axis=<span class="number">1</span>)</span><br><span class="line">confint = np.percentile(means, [<span class="number">2.5</span>, <span class="number">97.5</span>])</span><br><span class="line">print(confint)</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>原项目: <a href="https://github.com/rougier/numpy-100" target="_blank" rel="external nofollow noopener noreferrer">https://github.com/rougier/numpy-100</a></p>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Numpy" scheme="http://monteyang.cn/tags/Numpy/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>matplotlib颜色对照表</title>
<link href="http://monteyang.cn/matplotlib%E9%A2%9C%E8%89%B2%E5%AF%B9%E7%85%A7%E8%A1%A8.html"/>
<id>http://monteyang.cn/matplotlib%E9%A2%9C%E8%89%B2%E5%AF%B9%E7%85%A7%E8%A1%A8.html</id>
<published>2020-05-08T01:26:36.000Z</published>
<updated>2020-05-08T09:31:43.452Z</updated>
<content type="html"><![CDATA[<p>matplotlib 颜色对照</p><a id="more"></a><p><img data-src="../images/matplotlib-color-1024x1008.png" alt="matplotlib颜色对照"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br></pre></td><td class="code"><pre><span class="line">cnames = {</span><br><span class="line"><span class="string">'aliceblue'</span>: <span class="string">'#F0F8FF'</span>,</span><br><span class="line"><span class="string">'antiquewhite'</span>: <span class="string">'#FAEBD7'</span>,</span><br><span class="line"><span class="string">'aqua'</span>: <span class="string">'#00FFFF'</span>,</span><br><span class="line"><span class="string">'aquamarine'</span>: <span class="string">'#7FFFD4'</span>,</span><br><span class="line"><span class="string">'azure'</span>: <span class="string">'#F0FFFF'</span>,</span><br><span class="line"><span class="string">'beige'</span>: <span class="string">'#F5F5DC'</span>,</span><br><span class="line"><span class="string">'bisque'</span>: <span class="string">'#FFE4C4'</span>,</span><br><span class="line"><span class="string">'black'</span>: <span class="string">'#000000'</span>,</span><br><span class="line"><span class="string">'blanchedalmond'</span>: <span class="string">'#FFEBCD'</span>,</span><br><span class="line"><span class="string">'blue'</span>: <span class="string">'#0000FF'</span>,</span><br><span class="line"><span class="string">'blueviolet'</span>: <span class="string">'#8A2BE2'</span>,</span><br><span class="line"><span class="string">'brown'</span>: <span class="string">'#A52A2A'</span>,</span><br><span class="line"><span class="string">'burlywood'</span>: <span class="string">'#DEB887'</span>,</span><br><span class="line"><span class="string">'cadetblue'</span>: <span class="string">'#5F9EA0'</span>,</span><br><span class="line"><span class="string">'chartreuse'</span>: <span class="string">'#7FFF00'</span>,</span><br><span class="line"><span class="string">'chocolate'</span>: <span class="string">'#D2691E'</span>,</span><br><span class="line"><span class="string">'coral'</span>: <span class="string">'#FF7F50'</span>,</span><br><span class="line"><span class="string">'cornflowerblue'</span>: <span class="string">'#6495ED'</span>,</span><br><span class="line"><span class="string">'cornsilk'</span>: <span class="string">'#FFF8DC'</span>,</span><br><span class="line"><span class="string">'crimson'</span>: <span class="string">'#DC143C'</span>,</span><br><span class="line"><span class="string">'cyan'</span>: <span class="string">'#00FFFF'</span>,</span><br><span class="line"><span class="string">'darkblue'</span>: <span class="string">'#00008B'</span>,</span><br><span class="line"><span class="string">'darkcyan'</span>: <span class="string">'#008B8B'</span>,</span><br><span class="line"><span class="string">'darkgoldenrod'</span>: <span class="string">'#B8860B'</span>,</span><br><span class="line"><span class="string">'darkgray'</span>: <span class="string">'#A9A9A9'</span>,</span><br><span class="line"><span class="string">'darkgreen'</span>: <span class="string">'#006400'</span>,</span><br><span class="line"><span class="string">'darkkhaki'</span>: <span class="string">'#BDB76B'</span>,</span><br><span class="line"><span class="string">'darkmagenta'</span>: <span class="string">'#8B008B'</span>,</span><br><span class="line"><span class="string">'darkolivegreen'</span>: <span class="string">'#556B2F'</span>,</span><br><span class="line"><span class="string">'darkorange'</span>: <span class="string">'#FF8C00'</span>,</span><br><span class="line"><span class="string">'darkorchid'</span>: <span class="string">'#9932CC'</span>,</span><br><span class="line"><span class="string">'darkred'</span>: <span class="string">'#8B0000'</span>,</span><br><span class="line"><span class="string">'darksalmon'</span>: <span class="string">'#E9967A'</span>,</span><br><span class="line"><span class="string">'darkseagreen'</span>: <span class="string">'#8FBC8F'</span>,</span><br><span class="line"><span class="string">'darkslateblue'</span>: <span class="string">'#483D8B'</span>,</span><br><span class="line"><span class="string">'darkslategray'</span>: <span class="string">'#2F4F4F'</span>,</span><br><span class="line"><span class="string">'darkturquoise'</span>: <span class="string">'#00CED1'</span>,</span><br><span class="line"><span class="string">'darkviolet'</span>: <span class="string">'#9400D3'</span>,</span><br><span class="line"><span class="string">'deeppink'</span>: <span class="string">'#FF1493'</span>,</span><br><span class="line"><span class="string">'deepskyblue'</span>: <span class="string">'#00BFFF'</span>,</span><br><span class="line"><span class="string">'dimgray'</span>: <span class="string">'#696969'</span>,</span><br><span class="line"><span class="string">'dodgerblue'</span>: <span class="string">'#1E90FF'</span>,</span><br><span class="line"><span class="string">'firebrick'</span>: <span class="string">'#B22222'</span>,</span><br><span class="line"><span class="string">'floralwhite'</span>: <span class="string">'#FFFAF0'</span>,</span><br><span class="line"><span class="string">'forestgreen'</span>: <span class="string">'#228B22'</span>,</span><br><span class="line"><span class="string">'fuchsia'</span>: <span class="string">'#FF00FF'</span>,</span><br><span class="line"><span class="string">'gainsboro'</span>: <span class="string">'#DCDCDC'</span>,</span><br><span class="line"><span class="string">'ghostwhite'</span>: <span class="string">'#F8F8FF'</span>,</span><br><span class="line"><span class="string">'gold'</span>: <span class="string">'#FFD700'</span>,</span><br><span class="line"><span class="string">'goldenrod'</span>: <span class="string">'#DAA520'</span>,</span><br><span class="line"><span class="string">'gray'</span>: <span class="string">'#808080'</span>,</span><br><span class="line"><span class="string">'green'</span>: <span class="string">'#008000'</span>,</span><br><span class="line"><span class="string">'greenyellow'</span>: <span class="string">'#ADFF2F'</span>,</span><br><span class="line"><span class="string">'honeydew'</span>: <span class="string">'#F0FFF0'</span>,</span><br><span class="line"><span class="string">'hotpink'</span>: <span class="string">'#FF69B4'</span>,</span><br><span class="line"><span class="string">'indianred'</span>: <span class="string">'#CD5C5C'</span>,</span><br><span class="line"><span class="string">'indigo'</span>: <span class="string">'#4B0082'</span>,</span><br><span class="line"><span class="string">'ivory'</span>: <span class="string">'#FFFFF0'</span>,</span><br><span class="line"><span class="string">'khaki'</span>: <span class="string">'#F0E68C'</span>,</span><br><span class="line"><span class="string">'lavender'</span>: <span class="string">'#E6E6FA'</span>,</span><br><span class="line"><span class="string">'lavenderblush'</span>: <span class="string">'#FFF0F5'</span>,</span><br><span class="line"><span class="string">'lawngreen'</span>: <span class="string">'#7CFC00'</span>,</span><br><span class="line"><span class="string">'lemonchiffon'</span>: <span class="string">'#FFFACD'</span>,</span><br><span class="line"><span class="string">'lightblue'</span>: <span class="string">'#ADD8E6'</span>,</span><br><span class="line"><span class="string">'lightcoral'</span>: <span class="string">'#F08080'</span>,</span><br><span class="line"><span class="string">'lightcyan'</span>: <span class="string">'#E0FFFF'</span>,</span><br><span class="line"><span class="string">'lightgoldenrodyellow'</span>: <span class="string">'#FAFAD2'</span>,</span><br><span class="line"><span class="string">'lightgreen'</span>: <span class="string">'#90EE90'</span>,</span><br><span class="line"><span class="string">'lightgray'</span>: <span class="string">'#D3D3D3'</span>,</span><br><span class="line"><span class="string">'lightpink'</span>: <span class="string">'#FFB6C1'</span>,</span><br><span class="line"><span class="string">'lightsalmon'</span>: <span class="string">'#FFA07A'</span>,</span><br><span class="line"><span class="string">'lightseagreen'</span>: <span class="string">'#20B2AA'</span>,</span><br><span class="line"><span class="string">'lightskyblue'</span>: <span class="string">'#87CEFA'</span>,</span><br><span class="line"><span class="string">'lightslategray'</span>: <span class="string">'#778899'</span>,</span><br><span class="line"><span class="string">'lightsteelblue'</span>: <span class="string">'#B0C4DE'</span>,</span><br><span class="line"><span class="string">'lightyellow'</span>: <span class="string">'#FFFFE0'</span>,</span><br><span class="line"><span class="string">'lime'</span>: <span class="string">'#00FF00'</span>,</span><br><span class="line"><span class="string">'limegreen'</span>: <span class="string">'#32CD32'</span>,</span><br><span class="line"><span class="string">'linen'</span>: <span class="string">'#FAF0E6'</span>,</span><br><span class="line"><span class="string">'magenta'</span>: <span class="string">'#FF00FF'</span>,</span><br><span class="line"><span class="string">'maroon'</span>: <span class="string">'#800000'</span>,</span><br><span class="line"><span class="string">'mediumaquamarine'</span>: <span class="string">'#66CDAA'</span>,</span><br><span class="line"><span class="string">'mediumblue'</span>: <span class="string">'#0000CD'</span>,</span><br><span class="line"><span class="string">'mediumorchid'</span>: <span class="string">'#BA55D3'</span>,</span><br><span class="line"><span class="string">'mediumpurple'</span>: <span class="string">'#9370DB'</span>,</span><br><span class="line"><span class="string">'mediumseagreen'</span>: <span class="string">'#3CB371'</span>,</span><br><span class="line"><span class="string">'mediumslateblue'</span>: <span class="string">'#7B68EE'</span>,</span><br><span class="line"><span class="string">'mediumspringgreen'</span>: <span class="string">'#00FA9A'</span>,</span><br><span class="line"><span class="string">'mediumturquoise'</span>: <span class="string">'#48D1CC'</span>,</span><br><span class="line"><span class="string">'mediumvioletred'</span>: <span class="string">'#C71585'</span>,</span><br><span class="line"><span class="string">'midnightblue'</span>: <span class="string">'#191970'</span>,</span><br><span class="line"><span class="string">'mintcream'</span>: <span class="string">'#F5FFFA'</span>,</span><br><span class="line"><span class="string">'mistyrose'</span>: <span class="string">'#FFE4E1'</span>,</span><br><span class="line"><span class="string">'moccasin'</span>: <span class="string">'#FFE4B5'</span>,</span><br><span class="line"><span class="string">'navajowhite'</span>: <span class="string">'#FFDEAD'</span>,</span><br><span class="line"><span class="string">'navy'</span>: <span class="string">'#000080'</span>,</span><br><span class="line"><span class="string">'oldlace'</span>: <span class="string">'#FDF5E6'</span>,</span><br><span class="line"><span class="string">'olive'</span>: <span class="string">'#808000'</span>,</span><br><span class="line"><span class="string">'olivedrab'</span>: <span class="string">'#6B8E23'</span>,</span><br><span class="line"><span class="string">'orange'</span>: <span class="string">'#FFA500'</span>,</span><br><span class="line"><span class="string">'orangered'</span>: <span class="string">'#FF4500'</span>,</span><br><span class="line"><span class="string">'orchid'</span>: <span class="string">'#DA70D6'</span>,</span><br><span class="line"><span class="string">'palegoldenrod'</span>: <span class="string">'#EEE8AA'</span>,</span><br><span class="line"><span class="string">'palegreen'</span>: <span class="string">'#98FB98'</span>,</span><br><span class="line"><span class="string">'paleturquoise'</span>: <span class="string">'#AFEEEE'</span>,</span><br><span class="line"><span class="string">'palevioletred'</span>: <span class="string">'#DB7093'</span>,</span><br><span class="line"><span class="string">'papayawhip'</span>: <span class="string">'#FFEFD5'</span>,</span><br><span class="line"><span class="string">'peachpuff'</span>: <span class="string">'#FFDAB9'</span>,</span><br><span class="line"><span class="string">'peru'</span>: <span class="string">'#CD853F'</span>,</span><br><span class="line"><span class="string">'pink'</span>: <span class="string">'#FFC0CB'</span>,</span><br><span class="line"><span class="string">'plum'</span>: <span class="string">'#DDA0DD'</span>,</span><br><span class="line"><span class="string">'powderblue'</span>: <span class="string">'#B0E0E6'</span>,</span><br><span class="line"><span class="string">'purple'</span>: <span class="string">'#800080'</span>,</span><br><span class="line"><span class="string">'red'</span>: <span class="string">'#FF0000'</span>,</span><br><span class="line"><span class="string">'rosybrown'</span>: <span class="string">'#BC8F8F'</span>,</span><br><span class="line"><span class="string">'royalblue'</span>: <span class="string">'#4169E1'</span>,</span><br><span class="line"><span class="string">'saddlebrown'</span>: <span class="string">'#8B4513'</span>,</span><br><span class="line"><span class="string">'salmon'</span>: <span class="string">'#FA8072'</span>,</span><br><span class="line"><span class="string">'sandybrown'</span>: <span class="string">'#FAA460'</span>,</span><br><span class="line"><span class="string">'seagreen'</span>: <span class="string">'#2E8B57'</span>,</span><br><span class="line"><span class="string">'seashell'</span>: <span class="string">'#FFF5EE'</span>,</span><br><span class="line"><span class="string">'sienna'</span>: <span class="string">'#A0522D'</span>,</span><br><span class="line"><span class="string">'silver'</span>: <span class="string">'#C0C0C0'</span>,</span><br><span class="line"><span class="string">'skyblue'</span>: <span class="string">'#87CEEB'</span>,</span><br><span class="line"><span class="string">'slateblue'</span>: <span class="string">'#6A5ACD'</span>,</span><br><span class="line"><span class="string">'slategray'</span>: <span class="string">'#708090'</span>,</span><br><span class="line"><span class="string">'snow'</span>: <span class="string">'#FFFAFA'</span>,</span><br><span class="line"><span class="string">'springgreen'</span>: <span class="string">'#00FF7F'</span>,</span><br><span class="line"><span class="string">'steelblue'</span>: <span class="string">'#4682B4'</span>,</span><br><span class="line"><span class="string">'tan'</span>: <span class="string">'#D2B48C'</span>,</span><br><span class="line"><span class="string">'teal'</span>: <span class="string">'#008080'</span>,</span><br><span class="line"><span class="string">'thistle'</span>: <span class="string">'#D8BFD8'</span>,</span><br><span class="line"><span class="string">'tomato'</span>: <span class="string">'#FF6347'</span>,</span><br><span class="line"><span class="string">'turquoise'</span>: <span class="string">'#40E0D0'</span>,</span><br><span class="line"><span class="string">'violet'</span>: <span class="string">'#EE82EE'</span>,</span><br><span class="line"><span class="string">'wheat'</span>: <span class="string">'#F5DEB3'</span>,</span><br><span class="line"><span class="string">'white'</span>: <span class="string">'#FFFFFF'</span>,</span><br><span class="line"><span class="string">'whitesmoke'</span>: <span class="string">'#F5F5F5'</span>,</span><br><span class="line"><span class="string">'yellow'</span>: <span class="string">'#FFFF00'</span>,</span><br><span class="line"><span class="string">'yellowgreen'</span>: <span class="string">'#9ACD32'</span>}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>matplotlib 颜色对照</p>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>深度强化学习-rainbow</title>
<link href="http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-rainbow.html"/>
<id>http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-rainbow.html</id>
<published>2020-04-29T22:51:47.000Z</published>
<updated>2020-05-08T09:32:01.736Z</updated>
<content type="html"><![CDATA[<p>集合了多种 DQN 的变体<br><a id="more"></a></p><ul><li>DQN</li><li>Double DQN</li><li>Dueling DQN</li><li>Prioritized Experience Replay</li><li>NoiseNet: (Noisy Networks for Exploration, AAAI2018)</li><li>Distributional RL: (A Distributional Perspective on Reinforcement Learning, ICML2017)</li></ul><p><img data-src="../images/RL-rainbow.png" alt></p><blockquote><p>参考<br>Rainbow: Combining Improvements in Deep Reinforcement Learning</p></blockquote>]]></content>
<summary type="html">
<p>集合了多种 DQN 的变体<br>
</summary>
<category term="强化学习" scheme="http://monteyang.cn/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="深度强化学习" scheme="http://monteyang.cn/tags/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>深度强化学习-Prioritized Experience Replay</title>
<link href="http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Prioritized%20Experience%20Replay.html"/>
<id>http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Prioritized%20Experience%20Replay.html</id>
<published>2020-04-29T18:27:16.000Z</published>
<updated>2020-05-08T09:30:46.265Z</updated>
<content type="html"><![CDATA[<h1 id="1-Problem"><a href="#1-Problem" class="headerlink" title="1. Problem"></a>1. Problem</h1><p>在之前的 DQN 算法中,一个重要思想是经验回放(Experience Replay),在训练过程中,从经验回放池对样本进行<strong>均匀采样</strong>。</p><p>在实际的问题中,样本往往有它们的优先级,因为有一些样本是相对“珍贵”的。</p><a id="more"></a><h1 id="2-Method"><a href="#2-Method" class="headerlink" title="2. Method"></a>2. Method</h1><p>优先级的经验回放(Prioritized Experience Replay)则是维护了一个<strong>带优先级</strong>的经验回放池,在这个经验池中:</p><ul><li>不同经验样本的<strong>优先权重不同</strong></li><li>优先权是<strong>用 TD 误差来衡量</strong>的</li><li>带优先级的经验回放池需要使用 sum-tree 以及 binary heap 数据结构实现</li><li>新来的经验样本(transition)的 TD 误差会被设置为最大</li></ul><p><img data-src="../images/RL-优先级经验回放-来源.png" alt="思想来源"></p><p>实际使用时,优先级经验回放会存在的问题:</p><p>TD 误差小的 transition 长时间难以采样到,过分关注 TD 误差大的样本,降低了样本的多样性。</p><p>解决方法:</p><ul><li>两种变体: $p_i = |\delta_i| + \epsilon$ 或 $p_i = 1/rank(i)$</li></ul><blockquote><p>参考<br>Prioritized Experience Replay (ICLR 2016)</p></blockquote>]]></content>
<summary type="html">
<h1 id="1-Problem"><a href="#1-Problem" class="headerlink" title="1. Problem"></a>1. Problem</h1><p>在之前的 DQN 算法中,一个重要思想是经验回放(Experience Replay),在训练过程中,从经验回放池对样本进行<strong>均匀采样</strong>。</p>
<p>在实际的问题中,样本往往有它们的优先级,因为有一些样本是相对“珍贵”的。</p>
</summary>
<category term="强化学习" scheme="http://monteyang.cn/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="深度强化学习" scheme="http://monteyang.cn/tags/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>深度强化学习-Dueling DQN</title>
<link href="http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Dueling%20DQN.html"/>
<id>http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Dueling%20DQN.html</id>
<published>2020-04-28T03:50:06.000Z</published>
<updated>2020-04-30T02:28:13.197Z</updated>
<content type="html"><![CDATA[<p>将 Q 函数分解成 V 函数和 A 函数(优势函数)</p><a id="more"></a><p><img data-src="../images/RL-Deuling-DQN-network.png" alt="网络结构"></p><p>优势:</p><ul><li>V 函数只关于状态,而 Q 函数关于状态-动作对,Q 函数的维度要高于 V 函数。所以学习 V 函数的机会更大,不需要估计每个动作的价值。</li><li>V 函数的泛化性能好,当有新动作加入时,不需要重新学习,只需要学习新动作的 A 函数即可。</li><li>减少了 Q 函数由于状态和动作的纬度差导致的噪声和突变</li></ul><p><img data-src="../images/RL-Dueling-DQN-来源.png" alt="思想来源"></p><blockquote><p>参考<br>Dueling Network Architectures for Deep Reinforcement (ICML2016)</p></blockquote>]]></content>
<summary type="html">
<p>将 Q 函数分解成 V 函数和 A 函数(优势函数)</p>
</summary>
<category term="强化学习" scheme="http://monteyang.cn/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="深度强化学习" scheme="http://monteyang.cn/tags/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>深度强化学习-Double DQN</title>
<link href="http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Double%20DQN.html"/>
<id>http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-Double%20DQN.html</id>
<published>2020-04-27T23:14:11.000Z</published>
<updated>2020-05-08T09:30:28.377Z</updated>
<content type="html"><![CDATA[<h1 id="1-Problem"><a href="#1-Problem" class="headerlink" title="1. Problem"></a>1. Problem</h1><p>Q learning 中存在<strong>过估计问题</strong>。过估计问题是指估计的值函数比真实值函数要大。</p><p>在计算 TD 目标值时,$r+\gamma max_a Q(s’,a)$ 中的 max 操作,会引入一个正向的偏差,导致目标值在很多情况下会偏大一些。</p><blockquote><p>例如,对于状态 s 下,如果对于所有的 a,真实的 Q(s, a) 均为 0,但是估计值由于不精确,会导致有些大于 0,有些小于 0。对估计值取最大,会引入一个正向的偏差。</p></blockquote><a id="more"></a><h1 id="2-Method"><a href="#2-Method" class="headerlink" title="2. Method"></a>2. Method</h1><p>Double DQN 的思想源于 Double Q-learning。</p><p><img data-src="../images/RL-double-dqn来源.png" alt></p><p>Double DQN 中考虑建模两个 Q 网络,一个用于<strong>选择动作</strong>,一个用于<strong>评估动作</strong>。网络 A 和 B 是相互独立的。</p><ul><li>网络 A:选择动作</li><li>网络 B:评估动作</li></ul><p>此时,TD 目标值的计算如下:</p><script type="math/tex; mode=display">r + \gamma Q^B(s', arg\max_a Q^A(s', a))</script><p><strong>在网络 A 中,依然选择的是 Q 值最大的动作,但这个动作对于网络 B 而言不一定是 Q 值最大的。在期望平均的情况下,可以抵消原来计算的正向偏差。</strong></p><p>Double Q-learning 伪代码:</p><p><img data-src="../images/RL-Double-dqn.png" alt></p><p>在代码实现中,原 DQN 算法中本身就有两个网络,只需要 target network 变成可更新的。</p><blockquote><p>参考<br>[1] Van Hasselt H, Guez A, Silver D. Deep reinforcement learning with double q-learning[C]//Thirtieth AAAI conference on artificial intelligence. 2016.</p></blockquote>]]></content>
<summary type="html">
<h1 id="1-Problem"><a href="#1-Problem" class="headerlink" title="1. Problem"></a>1. Problem</h1><p>Q learning 中存在<strong>过估计问题</strong>。过估计问题是指估计的值函数比真实值函数要大。</p>
<p>在计算 TD 目标值时,$r+\gamma max_a Q(s’,a)$ 中的 max 操作,会引入一个正向的偏差,导致目标值在很多情况下会偏大一些。</p>
<blockquote>
<p>例如,对于状态 s 下,如果对于所有的 a,真实的 Q(s, a) 均为 0,但是估计值由于不精确,会导致有些大于 0,有些小于 0。对估计值取最大,会引入一个正向的偏差。</p>
</blockquote>
</summary>
<category term="强化学习" scheme="http://monteyang.cn/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="深度强化学习" scheme="http://monteyang.cn/tags/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>深度强化学习-DQN</title>
<link href="http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-DQN.html"/>
<id>http://monteyang.cn/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0-DQN.html</id>
<published>2020-04-24T16:33:05.000Z</published>
<updated>2020-04-28T07:17:03.811Z</updated>
<content type="html"><![CDATA[<h1 id="深度强化学习简介"><a href="#深度强化学习简介" class="headerlink" title="深度强化学习简介"></a>深度强化学习简介</h1><p>简单说来,<code>深度学习 + 强化学习 = 深度强化学习</code>。即,使用深度神经网络作为强化学习中的函数近似器,近似强化学习中的值函数模型、策略函数模型。</p><a id="more"></a><hr><h1 id="DQN"><a href="#DQN" class="headerlink" title="DQN"></a>DQN</h1><p>DQN(Deep Q Network)算法源自论文《Human-level control through deep reinforcement learning》(Nature2015),这篇论文的算法框架基于传统强化学习中的 Q-learning(强化学习时间差分方法中已讲述)。在这里回顾一下 Q-learning:</p><p>Q-learning 方法是 off-policy 的时间差分方法。伪代码如图所示</p><p><img data-src="../images/Q-learning.jpg" alt></p><p>Q-learning 中有两个重要的概念:</p><ul><li>off-policy</li><li>时间差分</li></ul><p><strong>off-policy</strong> 是指<strong>行为策略(产生数据的策略)和目标策略不是一个策略</strong>。在 Q-learning 伪代码中,行为策略是$\epsilon -$贪婪策略,而要目标策略是贪婪策略(每个状态取值函数最大的那个动作)。</p><p><strong>时间差分方法</strong>,是指用时间差分目标值来更新当前行为值函数。在 Q-learning伪代码中,时间差分目标值为 $r_t + \gamma \max_a Q(s_{t+1}, a)$。</p><p>Q-learning 是1989年 Watkins 提出来的,2015年nature论文所提出的 DQN 是在Q-learning的基础上修改得到的。</p><p>DQN 对 Q-learning 的修改主要体现在以下3点:</p><ul><li>用深度卷积神经网络近似值函数</li><li>用<strong>经验回放机制</strong>对强化学习的学习过程进行训练</li><li>设置<strong>目标值函数网络</strong>来稳定时间差分算法中的 TD 误差</li></ul><p>下面对以上3点详细展开:</p><h2 id="1-深度卷积神经网络近似值函数"><a href="#1-深度卷积神经网络近似值函数" class="headerlink" title="1. 深度卷积神经网络近似值函数"></a>1. 深度卷积神经网络近似值函数</h2><p>神经网络拟合函数的好处,在之前(强化学习-值函数近似中)已经讲述过,此处不再赘述。</p><h2 id="2-经验回放机制"><a href="#2-经验回放机制" class="headerlink" title="2. 经验回放机制"></a>2. 经验回放机制</h2><p>对神经网络进行训练时,存在的假设是独立同分布。而通过强化学习采集到的数据之间存在着关联性,利用这些时间相关性强的数据进行训练,神经网络当然不稳定。经验回放机制可以<strong>打破数据间的关联</strong>。</p><p>在强化学习过程中,智能体将数据存储到一个数据库中,然后利用均匀随机采样的方法从数据库中抽取数据,然后利用抽取的数据对神经网络进行训练。</p><p><img data-src="../images/DQN-经验回放.png" alt></p><h2 id="3-目标值函数网络"><a href="#3-目标值函数网络" class="headerlink" title="3. 目标值函数网络"></a>3. 目标值函数网络</h2><p>与表格型的Q-learning算法,如图1.1所不同的是,利用神经网络对值函数进行逼近时,值函数的更新步更新的是参数[公式],更新方法是梯度下降法。因此图1.1中第6行值函数更新实际上变成了监督学习的一次更新过程,其梯度下降法为:</p><p><img data-src="https://www.zhihu.com/equation?tex=%5C%5B%0A%5Ctheta_%7Bt%2B1%7D%3D%5Ctheta_t%2B%5Calpha%5Cleft%5Br%2B%5Cgamma%5Cmax_%7Ba%27%7DQ%5Cleft%28s%27%2Ca%27%3B%5Ctheta%5Cright%29-Q%5Cleft%28s%2Ca%3B%5Ctheta%5Cright%29%5Cright%5D%5Cnabla+Q%5Cleft%28s%2Ca%3B%5Ctheta%5Cright%29%0A%5C%5D" alt></p><p>我们称计算TD目标时所用的网络为目标值函数网络。以往的神经网络逼近值函数时,计算TD目标的值函数所用的网络参数$\theta$,与梯度计算中要逼近的值函数用的网络参数相同,这样就容易使得数据间存在关联性,训练不稳定。为了解决这个问题,DeepMind提出:</p><ul><li>计算TD目标的网络表示为$\theta^-$</li><li>计算值函数逼近的网络表示为$\theta$</li><li>用于动作值函数逼近的网络每一步都更新,而用于计算TD目标的网络每个固定的步数更新一次</li></ul><h2 id="DQN-伪代码"><a href="#DQN-伪代码" class="headerlink" title="DQN 伪代码"></a>DQN 伪代码</h2><p><img data-src="../images/DQN伪代码.jpg" alt></p><p>算法流程:</p><ul><li>初始化<strong>经验回放池 D</strong>,可容纳 N 条数据</li><li>随机初始化值函数网络,权重$\theta$</li><li>初始化目标值函数网络 $\theta^- = \theta$(用来计算TD目标值)</li><li><code>for</code> 每个片段(episode):<ul><li>初始化第一个状态 $s_1={x_1}$,预处理得到状态对应的特征输入 $\phi_1=\phi(s_1)$</li><li><code>for</code> episode 中的每一步:<ul><li>通过 <strong>$\epsilon-$贪婪策略</strong> 选择动作 $a_t$</li><li>执行动作 $a_t$,获得奖励 $r_t$,新的图像 $x_{t+1}$</li><li>设置 $s_{t+1} = s_t, a_t, x_{t+1}$,预处理$\phi_{t+1}=\phi(s_{t+1})$</li><li>将转移作为样本$(\phi_t, a_t, r_t, \phi_{t+1})$ <strong>储存在经验池D</strong>中</li><li>从回放记忆D中随机批量采样转换样本数据(<strong>mini batch</strong>)。</li><li>利用<strong>目标值函数网络</strong>求 <strong>TD 目标值</strong>(target)</li><li>TD目标值和当前值函数作差为损失函数,进行梯度下降法,更新网络权重 $\theta$</li><li><strong>每隔 C 步,更新目标值函数网络</strong>的权重(用值函数网络的权重)</li></ul></li><li><code>end for</code></li></ul></li><li><code>end for</code></li></ul><blockquote><p>参考资料:<br><a href="https://zhuanlan.zhihu.com/p/26052182" target="_blank" rel="external nofollow noopener noreferrer">https://zhuanlan.zhihu.com/p/26052182</a><br>《Human-level control through deep reinforcement learning》(Nature2015)</p></blockquote>]]></content>
<summary type="html">
<h1 id="深度强化学习简介"><a href="#深度强化学习简介" class="headerlink" title="深度强化学习简介"></a>深度强化学习简介</h1><p>简单说来,<code>深度学习 + 强化学习 = 深度强化学习</code>。即,使用深度神经网络作为强化学习中的函数近似器,近似强化学习中的值函数模型、策略函数模型。</p>
</summary>
<category term="强化学习" scheme="http://monteyang.cn/categories/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="深度强化学习" scheme="http://monteyang.cn/tags/%E6%B7%B1%E5%BA%A6%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>编写高质量Python程序(四)库</title>
<link href="http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E5%9B%9B%EF%BC%89%E5%BA%93.html"/>
<id>http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E5%9B%9B%EF%BC%89%E5%BA%93.html</id>
<published>2020-04-20T06:05:31.000Z</published>
<updated>2020-04-24T16:34:02.132Z</updated>
<content type="html"><![CDATA[<blockquote><p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。</p><!-- > 首发于公众号【Python与算法之路】 --></blockquote><a id="more"></a><h2 id="按需选择-sort-或者-sorted"><a href="#按需选择-sort-或者-sorted" class="headerlink" title="按需选择 sort() 或者 sorted()"></a>按需选择 <code>sort()</code> 或者 <code>sorted()</code></h2><p>Python 中常用的排序函数有 <code>sort()</code> 和 <code>sorted()</code> </p><p>两者的函数形式分别如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sorted(iterable[, cmp[, key[, reverse]]])</span><br><span class="line">s.sort([cmp[, key[, reverse]]])</span><br></pre></td></tr></table></figure><p><code>sort()</code> 和 <code>sorted()</code> 有3个共同的参数:</p><ul><li><code>cmp</code> :<strong>用户定义的任何比较函数</strong>,函数的参数为两个可比较的元素(来自 iterable 或者 list ),函数根据第一个参数与第二个参数的关系依次返回 -1、0 或者 +1(第一个参数小于第二个参数则返回负数)。该参数默认值为 <code>None</code>。</li><li><code>key</code> 是一个带参数的函数,<strong>用来为每个元素提取比较值</strong>,默认为 <code>None</code>(即直接比较每个元素)</li><li><code>reverse</code> 表示排序<strong>结果是否反转</strong></li></ul><p>两者对比:</p><ul><li><p><code>sorted()</code> 作用于<strong>任何可迭代的对象</strong>;而 <code>sort()</code> 一般作用于<strong>列表</strong>。</p></li><li><p><code>sorted()</code> 函数会<strong>返回一个排序后的列表,原有列表保持不变</strong>;而 <code>sort()</code> 函数会<strong>直接修改原有列表</strong>,函数返回为 <code>None</code>。实际应用过程中需要保留原有列表,使用 <code>sorted()</code> 函数较为合适,否则可以选择 <code>sort()</code> 函数,因为 <code>sort()</code> 函数不需要复制原有列表,消耗的内存较少,效率也较高。</p></li><li>无论是 <code>sort()</code> 还是 <code>sorted()</code> 函数,传入参数 <code>key</code> 比传入参数 <code>cmp</code> 效率要高。<code>cmp</code> 传入的函数在整个排序过程中会调用多次,函数开销较大;而 <code>key</code> 针对每个元素仅做一次处理,因此使用 key 比使用 <code>cmp</code> 效率要高。</li><li><code>sorted()</code> 功能非常强大,它可以<strong>对不同的数据结构进行排序</strong>,从而满足不同需求。</li></ul><p>例:</p><p><strong>对字典进行排序</strong>:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>phone_book = {<span class="string">"Linda"</span>: <span class="string">"7750"</span>, <span class="string">"Bob"</span>: <span class="string">"9345"</span>, <span class="string">"Carol"</span>: <span class="string">"5834"</span>}</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">from</span> operator <span class="keyword">import</span> itemgetter</span><br><span class="line"><span class="meta">>>> </span>sorted_pb = sorted(phone_book.items(), key=itemgetter(<span class="number">1</span>))</span><br><span class="line"><span class="meta">>>> </span>print(sorted_pb)</span><br><span class="line">[(<span class="string">'Carol'</span>, <span class="string">'5834'</span>), (<span class="string">'Linda'</span>, <span class="string">'7750'</span>), (<span class="string">'Bob'</span>, <span class="string">'9345'</span>)]</span><br></pre></td></tr></table></figure><p><strong>多维 List 排序</strong>:实际情况下也会碰到需要对多个字段进行排序的情况,这在 DB 里面用 SQL 语句很容易做到,但使用多维列表联合 <code>sorted()</code> 函数也可以轻易达到</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> operator</span><br><span class="line"><span class="meta">>>> </span>game_result = [[<span class="string">"Bob"</span>,<span class="number">95</span>,<span class="string">"A"</span>],[<span class="string">"Alan"</span>,<span class="number">86</span>,<span class="string">"C"</span>],[<span class="string">"Mandy"</span>,<span class="number">82.5</span>,<span class="string">"A"</span>],[<span class="string">"Rob"</span>,<span class="number">86</span>,<span class="string">"E"</span>]]</span><br><span class="line"><span class="meta">>>> </span>sorted(game_result, key=operator.itemgetter(<span class="number">2</span>, <span class="number">1</span>))</span><br><span class="line">[[<span class="string">'Mandy'</span>, <span class="number">82.5</span>, <span class="string">'A'</span>], [<span class="string">'Bob'</span>, <span class="number">95</span>, <span class="string">'A'</span>], [<span class="string">'Alan'</span>, <span class="number">86</span>, <span class="string">'C'</span>], [<span class="string">'Rob'</span>, <span class="number">86</span>, <span class="string">'E'</span>]]</span><br></pre></td></tr></table></figure><p><strong>字典中混合 List 排序</strong>:字典中的 key 或者值为列表,对列表中的某一个位置的元素排序</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>my_dict = {<span class="string">"Li"</span>:[<span class="string">"M"</span>,<span class="number">7</span>],<span class="string">"Zhang"</span>:[<span class="string">"E"</span>,<span class="number">2</span>],<span class="string">"Wang"</span>:[<span class="string">"P"</span>,<span class="number">3</span>],<span class="string">"Du"</span>:[<span class="string">"C"</span>,<span class="number">2</span>],<span class="string">"Ma"</span>:[<span class="string">"C"</span>,<span class="number">9</span>],<span class="string">"Zhe"</span>:[<span class="string">"H"</span>,<span class="number">7</span>]}</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> operator</span><br><span class="line"><span class="meta">>>> </span>sorted(my_dict.items(), key=<span class="keyword">lambda</span> item:operator.itemgetter(<span class="number">1</span>)(item[<span class="number">1</span>]))</span><br><span class="line">[(<span class="string">'Du'</span>, [<span class="string">'C'</span>, <span class="number">2</span>]), (<span class="string">'Zhang'</span>, [<span class="string">'E'</span>, <span class="number">2</span>]), (<span class="string">'Wang'</span>, [<span class="string">'P'</span>, <span class="number">3</span>]), (<span class="string">'Zhe'</span>, [<span class="string">'H'</span>, <span class="number">7</span>]), (<span class="string">'Li'</span>, [<span class="string">'M'</span>, <span class="number">7</span>]), (<span class="string">'Ma'</span>, [<span class="string">'C'</span>, <span class="number">9</span>])]</span><br></pre></td></tr></table></figure><p><strong>List 中混合字典排序</strong>:列表中的每一个元素为字典形式,针对字典的多个 key 值进行排序</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">import</span> operator</span><br><span class="line"><span class="meta">>>> </span>game_result = [{<span class="string">"name"</span>:<span class="string">"Bob"</span>,<span class="string">"wins"</span>:<span class="number">10</span>,<span class="string">"losses"</span>:<span class="number">3</span>,<span class="string">"rating"</span>:<span class="number">75</span>},{<span class="string">"name"</span>:<span class="string">"David"</span>,<span class="string">"wins"</span>:<span class="number">3</span>,<span class="string">"losses"</span>:<span class="number">5</span>,<span class="string">"rating"</span>:<span class="number">57</span>},{<span class="string">"name"</span>:<span class="string">"Carol"</span>,<span class="string">"wins"</span>:<span class="number">4</span>,<span class="string">"losses"</span>:<span class="number">5</span>,<span class="string">"rating"</span>:<span class="number">57</span>},{<span class="string">"name"</span>:<span class="string">"Patty"</span>,<span class="string">"wins"</span>:<span class="number">9</span>,<span class="string">"losses"</span>:<span class="number">3</span>,<span class="string">"rating"</span>:<span class="number">71.48</span>}]</span><br><span class="line"><span class="meta">>>> </span>sorted(game_result, key=operator.itemgetter(<span class="string">"rating"</span>,<span class="string">"name"</span>))</span><br><span class="line">[{<span class="string">'losses'</span>: <span class="number">5</span>, <span class="string">'name'</span>: <span class="string">'Carol'</span>, <span class="string">'rating'</span>: <span class="number">57</span>, <span class="string">'wins'</span>: <span class="number">4</span>}, {<span class="string">'losses'</span>: <span class="number">5</span>, <span class="string">'name'</span>: <span class="string">'David'</span>, <span class="string">'rating'</span>: <span class="number">57</span>, <span class="string">'wins'</span>: <span class="number">3</span>}, {<span class="string">'losses'</span>: <span class="number">3</span>, <span class="string">'name'</span>: <span class="string">'Patty'</span>, <span class="string">'rating'</span>: <span class="number">71.48</span>, <span class="string">'wins'</span>: <span class="number">9</span>}, {<span class="string">'losses'</span>: <span class="number">3</span>, <span class="string">'name'</span>: <span class="string">'Bob'</span>, <span class="string">'rating'</span>: <span class="number">75</span>, <span class="string">'wins'</span>: <span class="number">10</span>}]</span><br></pre></td></tr></table></figure><h2 id="使用-copy-模块深拷贝对象"><a href="#使用-copy-模块深拷贝对象" class="headerlink" title="使用 copy 模块深拷贝对象"></a>使用 copy 模块深拷贝对象</h2><ul><li><strong>浅拷贝(shallow copy)</strong>:构造一个新的复合对象,并将从原对象中发现的引用插入该对象中。浅拷贝的实现方式有多种,如工厂函数、切片操作、copy 模块中的 <code>copy</code> 操作等。</li><li><strong>深拷贝(deep copy)</strong>:也构造一个新的复合对象,但是遇到引用会继续递归拷贝其所指向的具体内容,也就是说它会针对引用所指向的对象继续执行拷贝,因此产生的对象不受其他引用对象操作的影响。深拷贝的实现需要依赖 copy 模块的 <code>deepcopy()</code> 操作。</li></ul><p><strong>浅拷贝并不能进行彻底的拷贝,当存在列表、字典等不可变对象的时候,它仅仅拷贝其引用地址</strong>。要解决上述问题需要用到深拷贝,深拷贝不仅拷贝引用也拷贝引用所指向的对象,因此<strong>深拷贝得到的对象和原对象是相互独立的。</strong></p><h2 id="使用-Counter-进行计数统计"><a href="#使用-Counter-进行计数统计" class="headerlink" title="使用 Counter 进行计数统计"></a>使用 Counter 进行计数统计</h2><p>计数统计就是统计某一项出现的次数。可以使用不同数据结构来进行实现:</p><ul><li>例如,使用 <code>defaultdict</code>实现</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> defaultdict</span><br><span class="line">some_data = [<span class="string">"a"</span>, <span class="string">"2"</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">"2"</span>, <span class="string">"b"</span>, <span class="number">4</span>, <span class="number">7</span>, <span class="string">"a"</span>, <span class="number">5</span>, <span class="string">"d"</span>, <span class="string">"a"</span>, <span class="string">"z"</span>]</span><br><span class="line">count_frq = defaultdict(int)</span><br><span class="line"><span class="keyword">for</span> item <span class="keyword">in</span> some_data:</span><br><span class="line"> count_frq[item] += <span class="number">1</span></span><br><span class="line">print(count_frq)</span><br><span class="line"><span class="comment"># defaultdict(<class 'int'>, {'a': 3, '2': 2, 2: 1, 4: 2, 5: 2, 'b': 1, 7: 1, 'd': 1, 'z': 1})</span></span><br></pre></td></tr></table></figure><p>但<strong>更优雅,更 Pythonic 的解决方法是使用 <code>collections.Counter</code></strong>:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> Counter</span><br><span class="line">some_data = [<span class="string">"a"</span>, <span class="string">"2"</span>, <span class="number">2</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">"2"</span>, <span class="string">"b"</span>, <span class="number">4</span>, <span class="number">7</span>, <span class="string">"a"</span>, <span class="number">5</span>, <span class="string">"d"</span>, <span class="string">"z"</span>, <span class="string">"a"</span>]</span><br><span class="line">print(Counter(some_data))</span><br><span class="line"><span class="comment"># Counter({'a': 3, '2': 2, 4: 2, 5: 2, 2: 1, 'b': 1, 7: 1, 'd': 1, 'z': 1})</span></span><br></pre></td></tr></table></figure><h2 id="深入掌握-ConfigParser"><a href="#深入掌握-ConfigParser" class="headerlink" title="深入掌握 ConfigParser"></a>深入掌握 ConfigParser</h2><p>常见的配置文件格式有 XML 和 ini 等,其中在 MS Windows 系统上,ini 文件格式用得尤其多,甚至操作系统的 API 也都提供了相关的接口函数来支持它。类似 ini 的文件格式,在 Linux 等操作系统中也是极常用的,比如 pylint 的配置文件就是这个格式。Python 有个标准库来支持它,也就是 ConfigParser。</p><p>ConfigParser 的基本用法通过<a href="http://doc.codingdict.com/python_352/library/configparser.html" target="_blank" rel="external nofollow noopener noreferrer">手册</a>可以掌握,但仍然有几个知识点值得注意。首先就是 <code>getboolean()</code> 这个函数。<code>getboolean()</code> 根据一定的规则将配置项的值转换为布尔值,如以下的配置:<br><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[section1]</span></span><br><span class="line"><span class="attr">option1</span>=<span class="number">0</span></span><br></pre></td></tr></table></figure></p><p>当调用 <code>getboolean("section1", "option1")</code> 时,将返回 False。</p><p><strong><code>getboolean()</code> 的真值规则</strong>: 除了 0 以外,no、false 和 off 都会被转义为 False,而对应的 1、yes、true 和 on 则都被转义为 True,其他值都会导致抛出 <code>ValueError</code> 异常。</p><p>还需要注意的是配置项的查找规则。首先,在 ConfigParser 支持的配置文件格式里,有一个 <code>[DEFAULT]</code> 节,当读取的配置项不在指定的节里时,ConfigParser 将会到 <code>[DEFAULT]</code> 节中查找。<br>除此之外,还有一些机制导致项目对配置项的查找更复杂,这就是 class ConfigParser 构造函数中的 defaults 形参以及其 <code>get(section, option[, raw[, vars]])</code> 中的全名参数 <code>vars</code>。如果把这些机制全部用上,那么<strong>配置项值的查找规则</strong>:</p><ul><li>如果找不到节名,就抛出 NoSectionError</li><li>如果给定的配置项出现在 <code>get()</code> 方法的 <code>var</code> 参数中,则返回 <code>var</code> 参数中的值</li><li>如果在指定的节中含有给定的配置项,则返回其值</li><li>如果在 【DEFAULT】中有指定的配置项,则返回其值</li><li>如果在构造函数的 defaults 参数中有指定的配置项,则返回其值</li><li>抛出 NoOptionError</li></ul><h2 id="使用-argparse-处理命令行参数"><a href="#使用-argparse-处理命令行参数" class="headerlink" title="使用 argparse 处理命令行参数"></a>使用 argparse 处理命令行参数</h2><p>尽管应用程序通常能够通过配置文件在不修改代码的情况下改变行为,但提供灵活易用的命令行参数仍然非常有意义,比如:减轻用户的学习成本,通常命令行参数的用法只需要在应用程序名后面加 —help 参数就能获得,而配置文件的配置方法通常需要通读手册才能掌握。</p><p>关于命令行处理,现阶段<strong>最好用的</strong>参数处理标准库是 argparse。</p><ul><li><code>add_argument()</code> 方法用以增加一个参数声明。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line"></span><br><span class="line">parser = argparse.ArgumentParser(description=<span class="string">'Process some integers.'</span>)</span><br><span class="line">parser.add_argument(<span class="string">'integers'</span>, metavar=<span class="string">'N'</span>, type=int, nargs=<span class="string">'+'</span>,</span><br><span class="line"> help=<span class="string">'an integer for the accumulator'</span>)</span><br><span class="line">parser.add_argument(<span class="string">'--sum'</span>, dest=<span class="string">'accumulate'</span>, action=<span class="string">'store_const'</span>,</span><br><span class="line"> const=sum, default=max,</span><br><span class="line"> help=<span class="string">'sum the integers (default: find the max)'</span>)</span><br><span class="line"></span><br><span class="line">args = parser.parse_args()</span><br><span class="line">print(args.accumulate(args.integers))</span><br></pre></td></tr></table></figure><ul><li>除了支持常规的 int/float 等基本数值类型外,argparse 还<strong>支持文件类型</strong>,只要参数合法,程序就能够使用相应的文件描述符。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">parser = argparse.ArgumentParser()</span><br><span class="line">parser.add_argument(<span class="string">"bar"</span>, type=argparse.FileType(<span class="string">"w"</span>))</span><br><span class="line">parser.parse_args([<span class="string">"out.txt"</span>])</span><br></pre></td></tr></table></figure><ul><li><strong>扩展类型</strong>也变得更加容易,任何可调用对象,比如函数,都可以作为 type 的实参。另外 choices 参数也支持更多的类型,比如: <code>parser.add_argument("door", type=int, choices=range(1, 4))</code>。</li><li>此外,add_argument() 提供了对<strong>必填参数</strong>的支持,只要把 required 参数设置为 True 传递进去,当缺失这一参数时,argparse 就会自动退出程序,并提示用户。</li><li>还支持<strong>参数分组</strong>。add_argument_group() 可以在输出帮助信息时更加清晰,这在用法复杂的 CLI 应用程序中非常有帮助:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">parser = argparse.ArgumentParser(prog=<span class="string">"PROG"</span>, add_help=<span class="literal">False</span>)</span><br><span class="line">group1 = parser.add_argument_group(<span class="string">"group1"</span>, <span class="string">"group1 description"</span>)</span><br><span class="line">group1.add_argument(<span class="string">"foo"</span>, help=<span class="string">"foo help"</span>)</span><br><span class="line">group2 = parser.add_argument_group(<span class="string">"group2"</span>, <span class="string">"group2 description"</span>)</span><br><span class="line">group2.add_argument(<span class="string">"--bar"</span>, help=<span class="string">"bar help"</span>)</span><br><span class="line">parser.print_help()</span><br></pre></td></tr></table></figure><ul><li>另外还有 <code>add_mutually_exclusive_group(required=False)</code> 非常实用:它确保组中的<strong>参数至少有一个或者只有一个</strong>(required=True)。</li><li>argparse 也支持<strong>子命令</strong>,比如 <code>pip</code> 就有 <code>install/uninstall/freeze/list/show</code> 等子命令,这些子命令又接受不同的参数,使用 ArgumentParser.add_subparsers() 就可以实现类似的功能。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> argparse</span><br><span class="line">parser = argparse.ArgumentParser(prog=<span class="string">"PROG"</span>)</span><br><span class="line">subparsers = parser.add_subparsers(help=<span class="string">"sub-command help"</span>)</span><br><span class="line">parser_a = subparsers.add_parser(<span class="string">"a"</span>, help=<span class="string">"a help"</span>)</span><br><span class="line">parser_a.add_argument(<span class="string">"--bar"</span>, type=int, help=<span class="string">"bar help"</span>)</span><br><span class="line">parser.parse_args([<span class="string">"a"</span>, <span class="string">"--bar"</span>, <span class="string">"1"</span>])</span><br></pre></td></tr></table></figure><ul><li>除了参数处理之外,当出现<strong>非法参数</strong>时,用户还需要做一些处理,处理完成后,一般是输出提示信息并退出应用程序。ArgumentParser 提供了两个方法函数,分别是 <code>exit(status=0, message=None)</code> 和 <code>error(message)</code>,可以省了 <code>import sys</code> 再调用 <code>sys.exit()</code> 的步骤。</li></ul><h2 id="理解模块-pickle-优劣"><a href="#理解模块-pickle-优劣" class="headerlink" title="理解模块 pickle 优劣"></a>理解模块 pickle 优劣</h2><p>序列化,简单地说就是把内存中的数据结构在不丢失其身份和类型信息的情况下转换成对象的文本或二进制表示的过程。对象序列化后的形式经过反序列化过程应该能恢复原有对象。</p><p>Python 中有很多支持序列化的模块,如 pickle、json、marshal 和 shelve 等。</p><p><strong>pickle 是最通用的序列化模块</strong>,它还有个 C 语言的实现 cPickle,相比 pickle 来说具有较好的性能,其速度大概是 pickle 的 1000 倍,因此在大多数应用程序中应该优先使用 cPickle(注:cPickle 除了不能被继承之外,它们两者的使用基本上区别不大)。pickle 中最主要的两个函数对为 <code>dump()</code> 和 <code>load()</code>,分别用来进行对象的序列化和反序列化。</p><p>pickle 良好的特性总结为以下几点:</p><ul><li><strong>接口简单,容易使用</strong>。使用 <code>dump()</code> 和 <code>load()</code> 便可轻易实现序列化和反序列化。</li><li><strong>pickle 的存储格式具有通用性,能够被不同平台的 Python 解析器共享</strong>。比如 Linux 下序列化的格式文件可以在 Windows 平台的 Python 解析器上进行反序列化,兼容性较好。</li><li><strong>支持的数据类型广泛</strong>。如数字、布尔值、字符串,只包含可序列化对象的元组、字典、列表等,非嵌套的函数、类以及通过类的 <code>__dict__</code> 或者 <code>__getstate__()</code> 可以返回序列化对象的实例等。</li><li><p>pickle 模块是<strong>可以扩展</strong>的。对于实例对象,pickle 在还原对象的时候一般是不调用 <code>__init__()</code> 函数的,如果要调用 <code>__init__()</code> 进行初始化,对于古典类可以在类定义中提供 <code>__getinitargs__()</code> 函数,并返回一个元组,当进行 unpickle 的时候,Python 就会自动调用 <code>__init__()</code>,并把 <code>__getinitargs__()</code> 中返回的元组作为参数传递给 <code>__init__()</code>,而对于新式类,可以提供 <code>__getnewargs__()</code> 来提供对象生成时候的参数,在 unpickle 的时候以 <code>Class.__new__(Class, *arg)</code> 的方式创建对象。对于不可序列化的对象,如 sockets、文件句柄、数据库连接等,也可以通过实现 pickle 协议来解决这些巨献,主要是通过特殊方法 <code>__getstate__()</code> 和 <code>__setstate__()</code> 来返回实例在被 pickle 时的状态。</p><p> 示例:</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> cPickle <span class="keyword">as</span> pickle</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TextReader</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, filename)</span>:</span></span><br><span class="line"> self.filename = filename <span class="comment"># 文件名称</span></span><br><span class="line"> self.file = open(filename) <span class="comment"># 打开文件的句柄</span></span><br><span class="line"> self.postion = self.file.tell() <span class="comment"># 文件的位置</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">readline</span><span class="params">(self)</span>:</span></span><br><span class="line"> line = self.file.readline()</span><br><span class="line"> self.postion = self.file.tell()</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> line:</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line"> <span class="keyword">if</span> line.endswith(<span class="string">"\n"</span>):</span><br><span class="line"> line = line[:<span class="number">-1</span>]</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"{}: {}"</span>.format(self.postion, line)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__getstate__</span><span class="params">(self)</span>:</span> <span class="comment"># 记录文件被 pickle 时候的状态</span></span><br><span class="line"> state = self.__dict__.copy() <span class="comment"># 获取被 pickle 时的字典信息</span></span><br><span class="line"> <span class="keyword">del</span> state[<span class="string">"file"</span>]</span><br><span class="line"> <span class="keyword">return</span> state</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__setstate__</span><span class="params">(self, state)</span>:</span> <span class="comment"># 设置反序列化后的状态</span></span><br><span class="line"> self.__dict__.update(state)</span><br><span class="line"> file = open(self.filename)</span><br><span class="line"> self.file = file</span><br><span class="line"></span><br><span class="line">reader = TextReader(<span class="string">"zen.text"</span>)</span><br><span class="line">print(reader.readline())</span><br><span class="line">print(reader.readline())</span><br><span class="line">s = pickle.dumps(reader) <span class="comment"># 在 dumps 的时候会默认调用 __getstate__</span></span><br><span class="line">new_reader = pickle.loads(s) <span class="comment"># 在 loads 的时候会默认调用 __setstate__</span></span><br><span class="line">print(new_reader.readline())</span><br></pre></td></tr></table></figure></li><li><p>能够自动维护对象间的引用,如果一个对象上存在多个引用,pickle 后不会改变对象间的引用,并且能够自动处理循环和递归引用。</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>a = [<span class="string">"a"</span>, <span class="string">"b"</span>]</span><br><span class="line"><span class="meta">>>> </span>b = a <span class="comment"># b 引用对象 a</span></span><br><span class="line"><span class="meta">>>> </span>b.append(<span class="string">"c"</span>)</span><br><span class="line"><span class="meta">>>> </span>p = pickle.dumps((a, b))</span><br><span class="line"><span class="meta">>>> </span>a1, b1 = pickle.loads(p)</span><br><span class="line"><span class="meta">>>> </span>a1</span><br><span class="line">[<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>]</span><br><span class="line"><span class="meta">>>> </span>b1</span><br><span class="line">[<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>]</span><br><span class="line"><span class="meta">>>> </span>a1.append(<span class="string">"d"</span>) <span class="comment"># 反序列化对 a1 对象的修改仍然会影响到 b1</span></span><br><span class="line"><span class="meta">>>> </span>b1</span><br><span class="line">[<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>, <span class="string">"d"</span>]</span><br></pre></td></tr></table></figure><p>但 pickle 使用也存在以下一些限制:</p></li><li><strong>pickle 不能保证操作的原子性</strong>。pickle 并不是原子操作,也就是说在一个 pickle 调用中如果发生异常,可能部分数据已经被保存,另外如果对象处于深递归状态,那么可能超出 Python 的最大递归深度。递归深度可以通过 <code>sys.setrecursionlimit()</code> 进行扩展。</li><li><strong>pickle 存在安全性问题</strong>。Python 的文档清晰地表明它不提供安全性保证,因此对于一个从不可信的数据源接收到的数据不要轻易进行反序列化。由于 loads() 可以接收字符串作为参数,精心设计的字符串给入侵提供了一种可能。在 Python 解释器中输入代码 <code>pickle.loads("cos\nsystem\n(S'dir\ntR.")</code>便可以查看当前目录下所有文件。可以将 dir 替换为其他更具破坏性的命令。如果要进一步提高安全性,用户可以通过继承类 pickle.Unpickler 并重写 <code>find_class()</code> 方法来实现。</li><li><strong>pickle 协议是 Python 特定的,不同语言之间的兼容性难以保障</strong>。用 Python 创建的 pickle 文件可能其他语言不能使用。</li></ul><h2 id="序列化的另一个不错的选择——JSON"><a href="#序列化的另一个不错的选择——JSON" class="headerlink" title="序列化的另一个不错的选择——JSON"></a>序列化的另一个不错的选择——JSON</h2><p>Python 的标准库 JSON 提供的最常用的方法与 pickle 类似,dump/dumps 用来序列化,load/loads 用来反序列化。需要注意 json 默认不支持非 ASCII-based 的编码,如 load 方法可能在处理中文字符时不能正常显示,则需要通过 encoding 参数指定对应的字符编码。在序列化方面,相比 pickle,JSON 具有以下优势:</p><ul><li>使用简单,<strong>支持多种数据类型</strong>。JSON 文档的构成非常简单,仅存在以下两大数据结构:<ul><li><strong>名称/值对的集合</strong>。在各种语言中,它被实现为一个对象、记录、结构、字典、散列表、键列表或关联数组。</li><li><strong>值的有序列表</strong>。在大多数语言中,它被实现为数组、向量、列表或序列。在 Python 中对应支持的数据类型包括字典、列表、字符串、整数、浮点数、True、False、None 等。JSON 中数据结构和 Python 中的转换并不是完全一一对应,存在一定的差异。</li></ul></li><li><strong>存储格式可读性更为友好,容易修改</strong>。相比于 pickle 来说,json 格式更加接近程序员的思维,阅读和修改上要容易得多。dumps() 函数提供了一个参数 indent 使生成的 json 文件可读性更好,0 意味着“每个值单独一行”;大于 0 的数字意味着“每个值单独一行并且使用这个数字的空格来缩进嵌套的数据结构”。但需要注意的是,这个参数是以文件大小变大为代价的。</li><li><strong>json 支持跨平台跨语言操作</strong>。如 Python 中生成的 json 文件可以轻易使用 JavaScript 解析,互操作性更强,而 pickle 格式的文件只能在 Python 语言中支持。此外 json 原生的 JavaScript 支持,客户端浏览器不需要为此使用额外的解释器,特别适用于 Web 应用提供快速、紧凑、方便地序列化操作。此外,相比于 pickle,json 的存储格式更为紧凑,所占空间更小。</li><li><strong>具有较强的扩展性</strong>。json 模块还提供了编码(JSONEncoder)和解码类(JSONDecoder)以便用户对其默认不支持的序列化类型进行扩展。</li></ul><p>Python 中标准模块 json 的性能比 pickle 与 cPickle 稍逊。如果对序列化性能要求非常高的场景,可以使用 cPickle 模块。</p><h2 id="使用-threading-模块编写多线程程序"><a href="#使用-threading-模块编写多线程程序" class="headerlink" title="使用 threading 模块编写多线程程序"></a>使用 threading 模块编写多线程程序</h2><p>GIL 的存在使得 Python 多线程编程暂时无法充分利用多处理器的优势,并不能提高运行速率,但在以下几种情况,如<strong>等待外部资源返回</strong>,或者<strong>为了提高用户体验而建立反应灵活的用户界面</strong>,或者<strong>多用户应用程序</strong>中,多线程仍然是一个比较好的解决方案。</p><p>Python 为多线程编程提供了两个非常简单明了的模块:thread 和 threading。</p><p>thread 模块提供了多线程底层支持模块,以低级原始的方式来处理和控制线程,使用起来较为复杂;而 threading 模块基于 thread 进行包装,将线程的操作对象化,在语言层面提供了丰富的特性。实际应用中,<strong>推荐优先使用 threading 模块而不是 thread 模块。</strong></p><ul><li><p>就线程的<strong>同步和互斥</strong>来说,threading 模块中不仅有 Lock 指令锁,RLock 可重入指令锁,还支持条件变量 Condition、信号量 Semaphore、BoundedSemaphore 以及 Event 事件等。</p></li><li><p><strong>threading 模块主线程和子线程交互友好</strong>,<code>join()</code> 方法能够阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的 timeout(可选参数)。利用该方法可以方便地控制主线程和子线程以及子线程之间的执行。</p></li></ul><p>实际上很多情况下我们可能希望主线程能够等待所有子线程都完成时才退出,这时使用 threading 模块守护线程,可以通过 setDaemon() 函数来设定线程的 daemon 属性。当 daemon 属性设置为 True 的时候表明主线程的退出可以不用等待子线程完成。默认情况下,daemon 标志为 False,所有的非守护线程结束后主线程才会结束。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">myfunc</span><span class="params">(a, delay)</span>:</span></span><br><span class="line"> print(<span class="string">"I will calculate square of {} after delay for {}"</span>.format(a, delay))</span><br><span class="line"> time.sleep(delay)</span><br><span class="line"> print(<span class="string">"calculate begins..."</span>)</span><br><span class="line"> result = a * a</span><br><span class="line"> print(result)</span><br><span class="line"> <span class="keyword">return</span> result</span><br><span class="line"></span><br><span class="line">t1 = threading.Thread(target=myfunc, args=(<span class="number">2</span>, <span class="number">5</span>))</span><br><span class="line">t2 = threading.Thread(target=myfunc, args=(<span class="number">6</span>, <span class="number">8</span>))</span><br><span class="line">print(t1.isDaemon())</span><br><span class="line">print(t2.isDaemon())</span><br><span class="line">t2.setDaemon(<span class="literal">True</span>)</span><br><span class="line">t1.start()</span><br><span class="line">t2.start()</span><br></pre></td></tr></table></figure><h2 id="使用-Queue-使多线程编程更安全"><a href="#使用-Queue-使多线程编程更安全" class="headerlink" title="使用 Queue 使多线程编程更安全"></a>使用 Queue 使多线程编程更安全</h2><p>多线程编程不是件容易的事情。线程间的同步和互斥,线程间数据的共享等这些都是涉及线程安全要考虑的问题。</p><p>Python 中的 Queue 模块提供了 3 种队列:</p><ul><li><p><code>Queue.Queue(maxsize)</code>:<strong>先进先出</strong>,maxsize 为队列大小,其值为非正数的时候为无限循环队列</p></li><li><p><code>Queue.LifoQueue(maxsize)</code>:<strong>后进先出,相当于栈</strong></p></li><li><p><code>Queue.PriorityQueue(maxsize)</code>:<strong>优先级队列</strong></p></li></ul><p>这 3 种队列支持以下方法:</p><ul><li><code>Queue.qsize()</code>:返回队列大小。</li><li><code>Queue.empty()</code>:队列为空的时候返回 True,否则返回 False</li><li><code>Queue.full()</code>:当设定了队列大小的情况下,如果队列满则返回 True,否则返回 False。</li><li><code>Queue.put(item[, block[, timeout]])</code>:往队列中添加元素 item,block 设置为 False 的时候,如果队列满则抛出 Full 异常。如果 block 设置为 True,timeout 为 None 的时候则会一直等待直到有空位置,否则会根据 timeout 的设定超时后抛出 Full 异常。</li><li><code>Queue.put_nowait(item)</code>:等于 <code>put(item, False).block</code> 设置为 False 的时候,如果队列空则抛出 Empty 异常。如果 block 设置为 True、timeout 为 None 的时候则会一直等到有元素可用,否则会根据 timeout 的设定超时后抛出 Empty 异常。</li><li><code>Queue.get([block[, timeout]])</code>:从队列中删除元素并返回该元素的值</li><li><code>Queue.get_nowait()</code>:等价于 <code>get(False)</code></li><li><code>Queue.task_done()</code>:发送信号表明入列任务已经完成,经常在消费者线程中用到</li><li><code>Queue.join()</code>:阻塞直至队列中所有的元素处理完毕</li></ul><p>Queue 模块是<strong>线程安全</strong>的。需要注意的是, Queue 模块中的队列和 collections.deque 所表示的队列并不一样,前者主要用于不同线程之间的通信,它内部实现了线程的锁机制;而后者主要是数据结构上的概念。</p><p>多线程下载的例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> Queue</span><br><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"><span class="keyword">import</span> urllib2</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DownloadThread</span><span class="params">(threading.Thread)</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, queue)</span>:</span></span><br><span class="line"> threading.Thread.__init__(self)</span><br><span class="line"> self.queue = queue</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">run</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> url = self.queue.get() <span class="comment"># 从队列中取出一个 url 元素</span></span><br><span class="line"> print(self.name + <span class="string">"begin download"</span> + url + <span class="string">"..."</span>)</span><br><span class="line"> self.download_file(url) <span class="comment"># 进行文件下载</span></span><br><span class="line"> self.queue.task_done() <span class="comment"># 下载完毕发送信号</span></span><br><span class="line"> print(self.name + <span class="string">" download completed!!!"</span>)</span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">download_file</span><span class="params">(self, url)</span>:</span> <span class="comment"># 下载文件</span></span><br><span class="line"> urlhandler = urllib2.urlopen(url)</span><br><span class="line"> fname = os.path.basename(url) + <span class="string">".html"</span> <span class="comment"># 文件名称</span></span><br><span class="line"> <span class="keyword">with</span> open(fname, <span class="string">"wb"</span>) <span class="keyword">as</span> f: <span class="comment"># 打开文件</span></span><br><span class="line"> <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> chunk = urlhandler.read(<span class="number">1024</span>)</span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> chunk:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> f.write(chunk)</span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">"__main__"</span>:</span><br><span class="line"> urls = [<span class="string">"https://www.createspace.com/3611970"</span>,<span class="string">"http://wiki.python.org/moni.WebProgramming"</span>]</span><br><span class="line"> queue = Queue.Queue()</span><br><span class="line"> <span class="comment"># create a thread pool and give them a queue</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">5</span>):</span><br><span class="line"> t = DownloadThread(queue) <span class="comment"># 启动 5 个线程同时进行下载</span></span><br><span class="line"> t.setDaemon(<span class="literal">True</span>)</span><br><span class="line"> t.start()</span><br><span class="line"></span><br><span class="line"> <span class="comment"># give the queue some data</span></span><br><span class="line"> <span class="keyword">for</span> url <span class="keyword">in</span> urls:</span><br><span class="line"> queue.put(url)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># wait for the queue to finish</span></span><br><span class="line"> queue.join()</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<blockquote>
<p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。</p>
<!-- > 首发于公众号【Python与算法之路】 -->
</blockquote>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>编写高质量Python程序(三)基础语法</title>
<link href="http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%B8%89%EF%BC%89%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95.html"/>
<id>http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%B8%89%EF%BC%89%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95.html</id>
<published>2020-04-14T06:14:55.000Z</published>
<updated>2020-04-19T00:09:41.151Z</updated>
<content type="html"><![CDATA[<blockquote><p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。<br><!-- > 首发于公众号【Python与算法之路】 --></p></blockquote><a id="more"></a><h2 id="关于导入模块"><a href="#关于导入模块" class="headerlink" title="关于导入模块"></a>关于导入模块</h2><p>Python的3种引入外部模块的方式:<code>import</code>语句、<code>from ... import ...</code> 和 <code>__import__</code>函数。其中前两种比较常见。</p><p>在使用 <code>import</code> 时,应注意:</p><ul><li><strong>优先使用 <code>import A</code> 或 <code>import A as a</code></strong></li><li><strong>有节制的使用 <code>from A import B</code></strong></li><li><strong>尽量避免使用 <code>from A import *</code></strong></li></ul><p>对于 <code>from a import ...</code>,如果无节制的使用,会带来的问题:</p><ul><li>命名空间的冲突</li><li>循环嵌套导入的问题(两个文件相互导入对方的变量或函数或类)</li></ul><h2 id="i-1-不等于-i"><a href="#i-1-不等于-i" class="headerlink" title="i += 1 不等于 ++i"></a><code>i += 1</code> 不等于 <code>++i</code></h2><p>Python 解释器会将 <code>++i</code> 解释为 <code>+(+i)</code>,其中 <code>+</code> 表示正数符号。对于 <code>--i</code> 也是类似。</p><p>因此,要明白 <code>++i</code> 在 Python 的语法层面上是合法的,但并不是通常意义上的自增操作。</p><h2 id="使用-with-自动关闭资源"><a href="#使用-with-自动关闭资源" class="headerlink" title="使用 with 自动关闭资源"></a>使用 <code>with</code> 自动关闭资源</h2><p>对文件操作完成后,应该立即关闭它们,因为打开的文件不仅会占用系统资源,而且可能影响其他程序或者进程的操作,甚至会导致用户期望与实际操作结果不一致。</p><p>Python 提供了 with 语句,语法为:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">with</span> 表达式 [<span class="keyword">as</span> 目标]:</span><br><span class="line"> 代码块</span><br></pre></td></tr></table></figure><p>with 语句支持嵌套,支持多个 with 子句,它们两者可以相互转换。<code>with expr1 as e1, expr2 as e2</code>与下面的嵌套形式等价:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">with</span> expr1 <span class="keyword">as</span> e1:</span><br><span class="line"> <span class="keyword">with</span> expr2 <span class="keyword">as</span> e2:</span><br></pre></td></tr></table></figure><h2 id="使用-else-子句简化循环(异常处理)"><a href="#使用-else-子句简化循环(异常处理)" class="headerlink" title="使用 else 子句简化循环(异常处理)"></a>使用 <code>else</code> 子句简化循环(异常处理)</h2><p>在循环中, <code>else</code> 子句提供了隐含的对循环是否由 <code>break</code> 语句引发循环结束的判断。例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 以下两段代码等价</span></span><br><span class="line"><span class="comment"># 借助了一个标志量 found 来判断循环结束是不是由 break 语句引起的。</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">print_prime</span><span class="params">(n)</span>:</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">2</span>, n):</span><br><span class="line"> found = <span class="literal">True</span></span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> range(<span class="number">2</span>, i):</span><br><span class="line"> <span class="keyword">if</span> i % j == <span class="number">0</span>:</span><br><span class="line"> found = <span class="literal">False</span></span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> <span class="keyword">if</span> found:</span><br><span class="line"> print(<span class="string">"{} is a prime number"</span>.format(i))</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">print_prime2</span><span class="params">(n)</span>:</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">2</span>, n):</span><br><span class="line"> <span class="keyword">for</span> j <span class="keyword">in</span> range(<span class="number">2</span>, i):</span><br><span class="line"> <span class="keyword">if</span> i % j == <span class="number">0</span>:</span><br><span class="line"> <span class="keyword">break</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> print(<span class="string">"{} is a prime number"</span>.format(i))</span><br></pre></td></tr></table></figure><p>当循环“自然”终结(循环条件为假)时 <code>else</code> 从句会被执行一次,而当循环是由 <code>break</code> 语句中断时,<code>else</code> 子句就不被执行。</p><p>与 <code>for</code> 语句相似,<code>while</code> 语句中的 <code>else</code> 子句的语意是一样的: <code>else</code> 块在循环正常结束和循环条件不成立时被执行。</p><h2 id="遵循异常处理的几点基本原则"><a href="#遵循异常处理的几点基本原则" class="headerlink" title="遵循异常处理的几点基本原则"></a>遵循异常处理的几点基本原则</h2><p>Python中常用的异常处理语法是<code>try</code>、<code>except</code>、<code>else</code>、<code>finally</code>,它们可以有多种组合。语法形式如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Run this main action first</span></span><br><span class="line"><span class="keyword">try</span>:</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 当 try 中发生 name1 的异常时,进行处理</span></span><br><span class="line"><span class="keyword">except</span> <name1>:</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 当 try 中发生 name2 或 name3 中的某一个异常时</span></span><br><span class="line"><span class="keyword">except</span> (name2, name3):</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 当 try 中发生 name4 的异常时处理,并获取对应实例</span></span><br><span class="line"><span class="keyword">except</span> <name4> <span class="keyword">as</span> <data>:</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 其他异常时,进行处理</span></span><br><span class="line"><span class="keyword">except</span>:</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 没有异常时,执行</span></span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line"> <statements></span><br><span class="line"></span><br><span class="line"><span class="comment"># 无论有没有异常,都执行</span></span><br><span class="line"><span class="keyword">finally</span>:</span><br><span class="line"> <statements></span><br></pre></td></tr></table></figure><p>异常处理,通常需要遵循以下几点基本原则:</p><ul><li><strong>不推荐在 <code>try</code> 中放入过多的代码</strong>。在 try 中放入过多的代码带来的问题是如果程序中抛出异常,将会较难定位,给 debug 和修复带来不便,因此应尽量只在可能抛出异常的语句块前面放入 try 语句。</li><li>谨慎使用单独的 <code>except</code> 语句处理所有异常,<strong>最好能定位具体的异常</strong>。同样也不推荐使用 <code>except Exception</code> 或者 <code>except StandardError</code> 来捕获异常。如果必须使用,最好能够使用 <code>raise</code> 语句将异常抛出向上层传递。</li><li>注意异常捕获的顺序,在合适的层次处理异常。<ul><li>用户也可以继承自内建异常构建自己的异常类,从而在内建类的继承结构上进一步延伸。在这种情况下捕获异常的顺序显得非常重要。为了更精确地定位错误发生的原因,推荐的方法是将继承结构中子类异常在前面的 <code>except</code> 语句中抛出,而父类异常在后面的 <code>except</code> 语句抛出。这样做的原因是当 <code>try</code> 块中有异常发生的时候,解释器根据 <code>except</code> 声明的顺序进行匹配,在第一个匹配的地方便立即处理该异常。</li><li>异常捕获的顺序非常重要,同时异常应该在适当的位置被处理,一个原则就是<strong>如果异常能够在被捕获的位置被处理,那么应该及时处理,不能处理也应该以合适的方式向上层抛出。</strong>向上层传递的时候需要警惕异常被丢失的情况,可以使用不带参数的 raise 来传递。</li></ul></li><li>使用更为友好的异常信息,遵守异常参数的规范。通常来说有两类异常阅读者:使用软件的人和开发软件的人。</li></ul><h2 id="避免-finally-中可能发生的陷阱"><a href="#避免-finally-中可能发生的陷阱" class="headerlink" title="避免 finally 中可能发生的陷阱"></a>避免 finally 中可能发生的陷阱</h2><p>无论 <code>try</code> 语句中是否有异常抛出,<code>finally</code> 语句总会被执行。由于这个特性,<code>finally</code> 语句经常被用来做一些清理工作。<br>但使用 <code>finally</code> 时,也要特别小心一些陷阱。</p><ul><li>当 <code>try</code> 块中发生异常的时候,如果在 <code>except</code> 语句中找不到对应的异常处理,异常将会被临时保存起来,当 <code>finally</code> 执行完毕的时候,临时保存的异常将会再次被抛出,但如果 <code>finally</code> 语句中产生了新的异常或者执行了 <code>return</code> 或者 <code>break</code> 语句,那么临时保存的异常将会被丢失,从而导致异常屏蔽。</li><li>在实际应用程序开发过程中,并不推荐在 <code>finally</code> 中使用 <code>return</code> 语句进行返回,这种处理方式不仅会带来误解而且可能会引起非常严重的错误。</li></ul><h2 id="深入理解-None,正确判断对象是否为空"><a href="#深入理解-None,正确判断对象是否为空" class="headerlink" title="深入理解 None,正确判断对象是否为空"></a>深入理解 None,正确判断对象是否为空</h2><p>Python 中以下数据会当作空来处理:</p><ul><li>常量 <code>None</code></li><li>常量 <code>False</code></li><li>任何形式的数值类型零,如 <code>0</code>、<code>0L</code>、<code>0.0</code>、<code>0j</code></li><li>空的序列,如 <code>''</code>、<code>()</code>、<code>[]</code></li><li>空的字典,如 <code>{}</code></li><li>当用户定义的类中定义了 <code>__nonzero__()</code> 和 <code>__len__()</code> 方法,并且该方法返回整数 <code>0</code> 或 <code>False</code> 的时候。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> list1 <span class="comment"># value is not empty</span></span><br><span class="line"> Do something</span><br><span class="line"><span class="keyword">else</span>: <span class="comment"># value is empty</span></span><br><span class="line"> Do some other thing</span><br></pre></td></tr></table></figure><ul><li>执行过程中会调用内部方法 <code>__nonzero__()</code> 来判断变量 <code>list1</code> 是否为空并返回其结果。</li></ul><blockquote><p>注: <code>__nonzero__()</code> 方法 —— 该内部方法用于对自身对象进行空值测试,返回 0/1 或 True/False。</p></blockquote><ul><li>如果一个对象没有定义该方法,Python 将获取 <code>__len__()</code> 方法调用的结果来进行判断。<code>__len__()</code> 返回值为 0 则表示为空。如果一个类中既没有定义 <code>__len__()</code> 方法也没有定义 <code>__nonzero__()</code> 方法,该类的实例用 if 判断的结果都为 True。</li></ul><h2 id="格式化字符串时尽量使用-format-方式而不是"><a href="#格式化字符串时尽量使用-format-方式而不是" class="headerlink" title="格式化字符串时尽量使用 .format 方式而不是 %"></a>格式化字符串时尽量使用 <code>.format</code> 方式而不是 <code>%</code></h2><p>推荐尽量使用 <code>format</code> 方式而不是 <code>%</code> 操作符来格式化字符串,理由:</p><ul><li><code>format</code> 方式在使用上较 <code>%</code> 操作符更为灵活。使用 <code>format</code> 方式时,参数的顺序与格式化的顺序不必完全相同</li><li><p><code>format</code> 方式可以方便的作为参数传递</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">weather = [(<span class="string">"Monday"</span>, <span class="string">"rain"</span>), (<span class="string">"Tuesday"</span>, <span class="string">"sunny"</span>), (<span class="string">"Wednesday"</span>, <span class="string">"sunny"</span>), (<span class="string">"Thursday"</span>, <span class="string">"rain"</span>), (<span class="string">"Friday"</span>, <span class="string">"cloudy"</span>)]</span><br><span class="line">formatter = <span class="string">"Weather of '{0[0]}' is '{0[1]}'"</span>.format</span><br><span class="line"><span class="keyword">for</span> item <span class="keyword">in</span> map(formatter, weather):</span><br><span class="line"> print(item)</span><br></pre></td></tr></table></figure></li><li><p><code>%</code> 最终会被 .format 方式所代替。根据 Python 的官方文档,之所以仍然保留 <code>%</code> 操作符是为了保持向后兼容</p></li><li><code>%</code> 方法在某些特殊情况下使用时需要特别小心,对于 <code>%</code> 直接格式化字符的这种形式,如果字符本身为元组,则需要使用在 <code>%</code> 使用 <code>(itemname,)</code> 这种形式才能避免错误,注意逗号。</li></ul><h2 id="区别对待可变对象和不可变对象"><a href="#区别对待可变对象和不可变对象" class="headerlink" title="区别对待可变对象和不可变对象"></a>区别对待可变对象和不可变对象</h2><p>Python 中一切皆对象,对象根据其值能否修改分为<strong>可变对象</strong>和<strong>不可变对象</strong>。</p><ul><li><p>不可变对象</p><ul><li>数字</li><li>字符串</li><li>元组</li></ul></li><li><p>可变对象</p><ul><li>字典</li><li>列表</li><li>字节数组</li></ul></li></ul><p>在将可变对象<strong>作为函数默认参数</strong>的时候要特别紧惕,<strong>对可变对象的更改会直接影响原对象。</strong></p><p>最好的方法是传入 <code>None</code> 作为默认参数,在创建对象的时候动态生成可变对象。</p><ul><li><p>对于一个可变对象,<strong>切片操作相当于浅拷贝。</strong></p></li><li><p>对于不可变对象,当我们对其进行相关操作的时候,Python 实际上<strong>仍然保持原来的值而且重新创建一个新的对象</strong>,所以字符串对象不允许以索引的方式进行赋值,当有两个对象同时指向一个字符串对象的时候,对其中一个对象的操作并不会影响另一个对象。</p></li></ul><h2 id="函数传参既不是传值也不是传引用"><a href="#函数传参既不是传值也不是传引用" class="headerlink" title="函数传参既不是传值也不是传引用"></a>函数传参既不是传值也不是传引用</h2><p>对于Python中函数的传参方法,<strong>既不是传值,也不是传引用</strong>。</p><p>正确的叫法应该是<strong>传对象</strong>(call by object)或者说<strong>传对象的引用</strong>(call-by-object-reference)。</p><p>函数参数在传递的过程中将整个对象传入,</p><ul><li>对于<strong>可变对象</strong>:它的修改在函数外部以及内部都可见,调用者和被调用者之间共享这个对象</li><li>对于<strong>不可变对象</strong>:由于并不能真正被修改,因此,修改往往是通过生成一个新对象然后赋值来实现的</li></ul><h2 id="慎用变长参数"><a href="#慎用变长参数" class="headerlink" title="慎用变长参数"></a>慎用变长参数</h2><p>慎用可变长度参数<code>*args, **kwargs</code>,原因如下:</p><ul><li>使用过于灵活。变长参数意味着这个函数的签名不够清晰,存在多种调用方式。另外变长参数可能会破坏程序的健壮性。</li><li>如果一个函数的参数列表很长,虽然可以通过使用 <code>*args</code> 和 <code>**kwargs</code> 来简化函数的定义,但通常这个函数可以有更好的实现方式,应该被重构。例如可以直接传入元组和字典。</li></ul><p>可变长参数适合在下列情况下使用:</p><ul><li>为函数添加一个<strong>装饰器</strong></li><li>如果参数的数目不确定,可以考虑使用变长参数</li><li>用来实现函数的多态,或者在继承情况下子类需要调用父类的某些方法的时候</li></ul><h2 id="深入理解-str-和-repr-的区别"><a href="#深入理解-str-和-repr-的区别" class="headerlink" title="深入理解 str() 和 repr() 的区别"></a>深入理解 <code>str()</code> 和 <code>repr()</code> 的区别</h2><p>函数 <code>str()</code> 和 <code>repr()</code> 都可以将 Python 中的对象转换为字符串,两者的使用以及输出都非常相似。有以下几点区别:</p><ul><li><p>两者的目标不同:</p><ul><li><code>str()</code> 主要面向用户,其目的是可读性,返回形式为用户友好性和可读性都较强的字符串类型</li><li>而 <code>repr()</code> 面向开发人员,其目的是准确性,其返回值表示 Python 解释器内部的含义,常用作 debug</li></ul></li><li><p>在解释器中直接输入时默认调用 <code>repr()</code> 函数,而 <code>print</code> 则调用 <code>str()</code> 函数</p></li><li><code>repr()</code> 的返回值一般可以用 <code>eval()</code> 函数来还原对象。通常有如下等式:<code>obj == eval(repr(obj))</code></li><li>一般,类中都应该定义 <code>__repr__()</code> 方法,而 <code>__str__()</code> 方法则为可选,当可读性比准确性更为重要的时候应该考虑定义 <code>__str__()</code> 方法。如果类中没有定义 <code>__str__()</code> 方法,则默认会使用 <code>__repr__()</code> 方法的结果来返回对象的字符串表示形式。用户实现 <code>__repr__()</code> 方法的时,最好保证其返回值可以用 <code>eval()</code> 方法使对象重新还原。</li></ul><h2 id="分清静态方法和类方法的适用场景"><a href="#分清静态方法和类方法的适用场景" class="headerlink" title="分清静态方法和类方法的适用场景"></a>分清静态方法和类方法的适用场景</h2><p>静态方法:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span><span class="params">(object)</span>:</span></span><br><span class="line"><span class="meta"> @staticmethod</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(arg1, arg2, ...)</span>:</span></span><br></pre></td></tr></table></figure></p><p>类方法:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span><span class="params">(object)</span>:</span></span><br><span class="line"><span class="meta"> @classmethod</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">f</span><span class="params">(cls, arg1, arg2, ...)</span>:</span></span><br></pre></td></tr></table></figure></p><p>都可以通过<code>类名.方法名</code>或者<code>实例.方法名</code>的形式来访问。</p><p>其中,静态方法没有常规方法的特殊行为,如绑定、非绑定、隐式参数等规则,而类方法的调用使用类本身作为其隐含参数,但调用本身并不需要显示提供该参数。</p><p><strong>类方法</strong></p><ul><li>在调用的时候没有显式声明 cls,但实际上类本身是作为隐藏参数传入的</li><li>类方法可以判断出自己是通过基类被调用,还是通过某个子类被调用</li><li>类方法通过子类调用时,可以返回子类的属性而非基类的属性</li><li>类方法通过子类调用时,可以调用子类的其他类方法</li></ul><p><strong>静态方法</strong></p><ul><li>既不跟特定的实例相关也不跟特定的类相关</li><li>静态方法定义在类中的原因是,能够更加有效地将代码组织起来,从而使相关代码的垂直距离更近,提高代码的可维护性</li></ul>]]></content>
<summary type="html">
<blockquote>
<p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。<br><!-- > 首发于公众号【Python与算法之路】 --></p>
</blockquote>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>编写高质量Python程序(二)编程惯用法</title>
<link href="http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%BA%8C%EF%BC%89%E7%BC%96%E7%A8%8B%E6%83%AF%E7%94%A8%E6%B3%95.html"/>
<id>http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%BA%8C%EF%BC%89%E7%BC%96%E7%A8%8B%E6%83%AF%E7%94%A8%E6%B3%95.html</id>
<published>2020-04-10T02:37:25.000Z</published>
<updated>2020-04-11T13:05:39.923Z</updated>
<content type="html"><![CDATA[<blockquote><p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精炼汇总。</p></blockquote><a id="more"></a><h2 id="利用assert语句发现问题"><a href="#利用assert语句发现问题" class="headerlink" title="利用assert语句发现问题"></a>利用assert语句发现问题</h2><p>assert语句的基本语法如下:</p><p><code>assert expression1 ["," expression2]</code></p><p>其中,<code>expression1</code>是判断语句,会返回True或False,当返回False时会引发AssertionError。<code>[]</code>中的内容表示是可选的,用来传递具体的异常信息。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>a = <span class="number">1</span></span><br><span class="line"><span class="meta">>>> </span>b = <span class="number">2</span></span><br><span class="line"><span class="meta">>>> </span><span class="keyword">assert</span> a == b, <span class="string">"a equals b"</span></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">AssertionError: a equals b</span><br></pre></td></tr></table></figure><p>利用assert语句来发现程序中的问题。断言(assert)在很多语言中都存在,主要为调试程序服务,能够快速方便检查程序的异常或不恰当的输入。</p><p>要注意的是<strong>使用assert是有代价的,它会对性能产生一定的影响</strong>,可以不用尽量不用。</p><h2 id="两个变量进行数据交换"><a href="#两个变量进行数据交换" class="headerlink" title="两个变量进行数据交换"></a>两个变量进行数据交换</h2><p>变量进行数据交换值时,<strong>不推荐使用中间变量</strong>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 交换x,y</span></span><br><span class="line"><span class="comment"># 使用中间变量</span></span><br><span class="line">temp = x</span><br><span class="line">x = y</span><br><span class="line">y = temp</span><br><span class="line"><span class="comment"># 不使用中间变量</span></span><br><span class="line">x, y = y, x</span><br></pre></td></tr></table></figure><p>第二种方法在内存中执行的顺序如下:</p><ul><li>先计算右边的表达式 y, x,在内存中创建元组(y, x),其标示符合值分别为 y、x 及其对应的值,其中 y 和 x 是在初始化时已经存在于内存中的对象。</li><li>通过解包操作(unpacking),元组第一标识符(为 y)分配给左边第一个元素(此时为 x),元组第二个标识符(为 x)分配给左边第二个元素(为 y),从而达到实现 x、y 值交换的目的。</li></ul><h2 id="充分利用Lazy-evaluation的特性"><a href="#充分利用Lazy-evaluation的特性" class="headerlink" title="充分利用Lazy evaluation的特性"></a>充分利用Lazy evaluation的特性</h2><p>Lazy evaluation 常被译为“延迟计算”或“惰性计算”,指的是仅仅在真正需要执行的时候才计算表达式的值。</p><ul><li><strong>避免不必要的计算,带来性能上的提升</strong>。对于 Python 中的条件表达式 if x and y,在 x 为 false 的情况下 y 表达式的值将不再计算。而对于 if x or y,当 x 的值为 true 的时候将直接返回,不再计算 y 的值。</li><li>节省空间,使得无限循环的数据结构成为可能。Python 中最典型的使用延迟计算的例子就是<strong>生成器表达式</strong>了。比如斐波那契:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">fib</span><span class="params">()</span>:</span></span><br><span class="line"> a, b = <span class="number">0</span>, <span class="number">1</span></span><br><span class="line"> <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> <span class="keyword">yield</span> a</span><br><span class="line"> a, b = b, a + b</span><br><span class="line"><span class="keyword">from</span> itertools <span class="keyword">import</span> islice</span><br><span class="line">print(list(islice(fib(), <span class="number">5</span>)))</span><br></pre></td></tr></table></figure><h2 id="不推荐使用type来进行类型检查"><a href="#不推荐使用type来进行类型检查" class="headerlink" title="不推荐使用type来进行类型检查"></a>不推荐使用type来进行类型检查</h2><p>内建函数 type(object) 用于返回当前对象的类型。可以通过与 Python 自带模块 types 中所定义的名称进行比较,根据其返回值确定变量类型是否符合要求。</p><p>所有<strong>基本类型</strong>对应的名称都可以在 types 模块中找到,然而<strong>使用 type() 函数并不适合用来进行变量类型检查</strong>。这是因为:</p><ul><li>基于内建类型扩展的用户自定义类型,type 函数并不能准确返回结果</li><li>在古典类中,所有类的实例的 type 值都相等</li></ul><p>解决方法是,如果类型有对应的工厂函数,可以使用工厂函数对类型做相应转换,否则<strong>可以使用 isinstance() 函数来检测</strong>。</p><p><code>isinstance(object, classinfo)</code></p><p>其中,classinfo 可以为直接或间接类名、基本类型名称或者由它们组成的元组,该函数在 classinfo 参数错误的情况下会抛出 TypeError 异常。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># isinstance 基本用法举例如下:</span></span><br><span class="line"><span class="meta">>>> </span>isinstance(<span class="number">2</span>, float)</span><br><span class="line"><span class="literal">False</span></span><br><span class="line"><span class="meta">>>> </span>isinstance(<span class="string">"a"</span>, (str, unicode))</span><br><span class="line"><span class="literal">True</span></span><br><span class="line"><span class="meta">>>> </span>isinstance((<span class="number">2</span>, <span class="number">3</span>), (str, list, tuple)) <span class="comment"># 支持多种类型列表</span></span><br><span class="line"><span class="literal">True</span></span><br></pre></td></tr></table></figure><h2 id="警惕eval-的安全漏洞"><a href="#警惕eval-的安全漏洞" class="headerlink" title="警惕eval()的安全漏洞"></a>警惕eval()的安全漏洞</h2><p>Python中<code>eval()</code>函数将字符串当成有效的表达式来求值并返回计算结果。其函数声明如下:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">eval(expression[, globals[, locals]])</span><br></pre></td></tr></table></figure><br>其中,参数 globals 为字典形式,locals 为任何映射对象,它们分别表示全局和局部命名空间。如果传入 globals 参数的字典中缺少 <strong>builtins</strong> 的时候,当前的全局命名空间将作为 globals 参数输入并且在表达式计算之前被解析。locals 参数默认与 globals 相同,如果两者都省略的话,表达式将在 eval() 调用的环境中执行。</p><p>eval 存在安全漏洞,一个简单的例子:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> math <span class="keyword">import</span> *</span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ExpCalcBot</span><span class="params">(string)</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"Your answer is"</span>, eval(user_func) <span class="comment"># 计算输入的值</span></span><br><span class="line"> <span class="keyword">except</span> NameError:</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"The expression you enter is not valid"</span></span><br><span class="line"><span class="keyword">print</span> <span class="string">'Hi, I am ExpCalcBot. please input your expression or enter e to end'</span></span><br><span class="line">inputstr = <span class="string">''</span></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line"> <span class="keyword">print</span> <span class="string">'Please enter a number or operation. Enter c to complete. :'</span></span><br><span class="line"> inputstr = raw_input()</span><br><span class="line"> <span class="keyword">if</span> inputstr == str(<span class="string">'e'</span>): <span class="comment"># 遇到输入为 e 的时候退出</span></span><br><span class="line"> sys.exit()</span><br><span class="line"> <span class="keyword">elif</span> repr(inputstr) != repr(<span class="string">''</span>):</span><br><span class="line"> ExpCalcBot(inputstr)</span><br><span class="line"> inputstr = <span class="string">''</span></span><br></pre></td></tr></table></figure><p>由于网络环境下运行它的用户并非都是可信任的,比如输入 <code>__import__("os").system("dir")</code>,会显示当前目录下的所有文件列表;<strong>如果恶意输入<code>__import__("os").system("del * /Q")</code>,会导致当前目录下的所有文件都被删除了,而这一切没有任何提示。</strong></p><p>在 globals 参数中禁止全局命名空间的访问:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">ExpCalcBot</span><span class="params">(string)</span>:</span></span><br><span class="line"> <span class="keyword">try</span>:</span><br><span class="line"> math_fun_list = [<span class="string">"acos"</span>, <span class="string">"asin"</span>, <span class="string">"atan"</span>, <span class="string">"cos"</span>, <span class="string">"e"</span>, <span class="string">"log"</span>, <span class="string">"log10"</span>, <span class="string">"pi"</span>, <span class="string">"pow"</span>, <span class="string">"sin"</span>, <span class="string">"sqrt"</span>, <span class="string">"tan"</span>]</span><br><span class="line"> math_fun_dict = dict([(k, globals().get(k)) <span class="keyword">for</span> k <span class="keyword">in</span> math_fun_list]) <span class="comment"># 形成可以访问的函数的字典</span></span><br><span class="line"> <span class="keyword">print</span> <span class="string">"Your name is"</span>, eval(string, {<span class="string">"__builtins__"</span>: <span class="literal">None</span>}, math_fun_dict)</span><br><span class="line"> <span class="keyword">except</span> NameError:</span><br><span class="line"> <span class="keyword">print</span> <span class="string">"The expression you enter is not valid"</span></span><br></pre></td></tr></table></figure></p><p>再次进行恶意输入:<code>[c for c in ().__class__.__bases__[0].__subclasses__() if c.__name__ == "Quitter"][0](0)()</code>,</p><p><code># ().__class__.__bases__[0].__subclasses__()</code> 用来显示 object 类的所有子类。类 Quitter 与 “quit” 功能绑定,因此上面的输入会导致程序退出。</p><p><strong>对于有经验的侵入者来说,他可能会有一系列强大的手段,使得 eval 可以解释和调用这些方法,带来更大的破坏</strong>。此外,eval() 函数也给程序的调试带来一定困难,要查看 eval() 里面表达式具体的执行过程很难。因此在实际应用过程中如果使用对象不是信任源,<strong>应该避免使用 eval,在需要使用 eval 的地方可用安全性更好的<code>ast.literal_eval</code>替代。</strong></p><h2 id="使用enumerate-获取序列迭代的索引和值"><a href="#使用enumerate-获取序列迭代的索引和值" class="headerlink" title="使用enumerate()获取序列迭代的索引和值"></a>使用enumerate()获取序列迭代的索引和值</h2><p>使用函数 enumerate(),主要是为了解决在循环中获取索引以及对应值的问题。它具有一定的惰性(lazy),每次只在需要的时候才会产生一个(index, item)对。函数签名如下:</p><p><code>enumerate(sequence, start=0)</code></p><p>例子:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 使用 enumerate() 获取序列迭代的索引和值</span></span><br><span class="line">li = [<span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>, <span class="string">'e'</span>]</span><br><span class="line"><span class="keyword">for</span> i, e <span class="keyword">in</span> enumerate(li):</span><br><span class="line"> print(<span class="string">"index:"</span>, i, <span class="string">"element:"</span>, e)</span><br></pre></td></tr></table></figure></p><h2 id="区分-与is的适用场景"><a href="#区分-与is的适用场景" class="headerlink" title="区分==与is的适用场景"></a>区分==与is的适用场景</h2><ul><li><p><code>==</code>:用来检验两个对象的<strong>值</strong>是否相等的。它实际调用内部 <code>__eq__()</code> 方法,因此 <code>a == b</code> 相当于 <code>a.__eq__(b)</code>。</p></li><li><p><code>is</code>:用来<strong>比较两个对象在内存中是否拥有同一块内存空间</strong>。仅当 x 和 y 是同一个对象的时候才返回 True,<code>x is b</code> 基本相当于 <code>id(x) == id(y)</code>。</p></li></ul><p><code>==</code> 操作符也是可以被重载的,而 <code>is</code> 不能被重载。一般情况下,如果 <code>x is y</code> 为 True , <code>x == y</code> 的值一般也为 True(特殊情况除外,如 <code>NaN</code>,<code>a = float('NaN')</code>,<code>a is a</code> 为 True,<code>a == a</code> 为 false)。</p><h2 id="构建合理的包层次来管理模块"><a href="#构建合理的包层次来管理模块" class="headerlink" title="构建合理的包层次来管理模块"></a>构建合理的包层次来管理模块</h2><p>每一个 Python 文件都可以看成一个模块(module),使用模块可以增强代码的可维护性和可重用性。</p><p><strong>包即是目录</strong>,但与普通目录不同,它除了包含常规的 Python 文件(也就是模块)以外,还<strong>包含一个 <code>__init__.py</code> 文件,同时它允许嵌套</strong>。</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Package/<span class="module-access"><span class="module"><span class="identifier">__init__</span>.</span></span>py</span><br><span class="line"> <span class="module-access"><span class="module"><span class="identifier">Module1</span>.</span></span>py</span><br><span class="line"> <span class="module-access"><span class="module"><span class="identifier">Module2</span>.</span></span>py</span><br><span class="line"> Subpackage/<span class="module-access"><span class="module"><span class="identifier">__init__</span>.</span></span>py</span><br><span class="line"> <span class="module-access"><span class="module"><span class="identifier">Module1</span>.</span></span>py</span><br><span class="line"> <span class="module-access"><span class="module"><span class="identifier">Module2</span>.</span></span>py</span><br></pre></td></tr></table></figure><p>包中的模块可以通过”.”访问符进行访问,即”包名.模块名”。有以下几种导入方法:</p><ul><li><p>直接导入一个包:</p><p><code>import Package</code></p></li><li><p>导入子模块或子包,包嵌套的情况下可以进行嵌套导入:</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> Package <span class="keyword">import</span> Module1</span><br><span class="line"><span class="keyword">import</span> Package.Module1</span><br><span class="line"><span class="keyword">from</span> Package <span class="keyword">import</span> Subpackage</span><br><span class="line"><span class="keyword">import</span> Package.Subpackage</span><br><span class="line"><span class="keyword">from</span> Package.Subpackage <span class="keyword">import</span> Module1</span><br><span class="line"><span class="keyword">import</span> Package.Subpackage.Module1</span><br></pre></td></tr></table></figure></li></ul><p><code>__init__.py</code> 的作用:</p><ul><li>使包和普通目录区分</li><li>可以在该文件中申明模块级别的 import 语句,从而使其变成包级别可见</li></ul><p>如果 <code>__init__.py</code> 文件为空,当意图使用 <code>from Package import *</code> 将包 Package 中所有的模块导入当前名字空间时,并不能使得导入的模块生效,这是因为不同平台间的文件的命名规则不同,Python 解释器并不能正确判定模块在对应的平台该如何导入,因此仅仅执行 <code>__init__.py</code> 文件,<strong>如果要控制模块的导入,则需要对 <code>__init__.py</code> 文件做修改。</strong></p><p><code>__init__.py</code> 文件还有一个作用就是通过在该文件中定义 <code>__all__</code> 变量,控制需要导入的子包或者模块。之后再运行 <code>from ... import *</code>,可以看到 <code>__all__</code> 变量中定义的模块和包被导入当前名字空间。</p><p>包的使用能够带来以下便利:</p><ul><li>合理组织代码,便于维护和使用</li><li>能够有效地避免名称空间冲突</li></ul><p>如果模块包含的属性和方法存在同名冲突,使用 <code>import module</code> <strong>可以有效地避免名称冲突</strong>。在嵌套的包结构中,每一个模块都以其所在的完整路径作为其前缀,因此,即使名称一样,但由于模块所对应的其前缀不同,就不会产生冲突。</p>]]></content>
<summary type="html">
<blockquote>
<p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精炼汇总。</p>
</blockquote>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>编写高质量Python程序(一)引论</title>
<link href="http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%B8%80%EF%BC%89%E5%BC%95%E8%AE%BA.html"/>
<id>http://monteyang.cn/%E7%BC%96%E5%86%99%E9%AB%98%E8%B4%A8%E9%87%8FPython%E7%A8%8B%E5%BA%8F%EF%BC%88%E4%B8%80%EF%BC%89%E5%BC%95%E8%AE%BA.html</id>
<published>2020-04-09T17:45:35.000Z</published>
<updated>2020-04-22T14:10:54.691Z</updated>
<content type="html"><![CDATA[<blockquote><p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。</p></blockquote><a id="more"></a><h1 id="理解Pythonic概念"><a href="#理解Pythonic概念" class="headerlink" title="理解Pythonic概念"></a>理解Pythonic概念</h1><ul><li><p>什么是 Pythonic?</p><p>Pythonic的代码就是具有Python独特风格的代码。通俗说来,就是在保证代码可读性的前提下,尽可能地简洁、优雅,看起来像伪代码一样。</p></li><li><p>具有 Python 代码风格的例子</p><ul><li><strong>交换两个变量</strong>。其他语言交换两个变量时,一般需要一个临时的中间变量,而Python中可以用一行代码直接交换。</li><li><strong>for循环直接遍历容器</strong>。其他语言中,需要根据索引下标i对容器进行遍历,而Python可以用for循环直接遍历容器。</li><li><strong>使用 <code>str.format()</code> 格式化字符串</strong>,是最Pythonic的字符串格式化方法。</li></ul></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 交换两个变量</span></span><br><span class="line">a, b = b, a</span><br><span class="line"></span><br><span class="line"><span class="comment"># for循环遍历容器</span></span><br><span class="line"><span class="keyword">for</span> elem <span class="keyword">in</span> alist:</span><br><span class="line"> do_sth_with(elem)</span><br><span class="line"></span><br><span class="line"><span class="comment"># format格式化字符串</span></span><br><span class="line">print(<span class="string">"{greet} from {language}!"</span>.format(greet=<span class="string">"hello, world!"</span>, language=<span class="string">"Python"</span>))</span><br></pre></td></tr></table></figure><ul><li>Python的库和框架:现有的框架就好比现有的“轮子”,学会利用这些框架,不重复造轮子。</li></ul><h1 id="编写Pythonic代码"><a href="#编写Pythonic代码" class="headerlink" title="编写Pythonic代码"></a>编写Pythonic代码</h1><p>注意要避免的事:</p><ul><li>避免只用大小写来区分不同的对象。</li><li>避免使用容易混淆的名称。</li><li>不要害怕过长的变量名。能表达清楚变量代表的含义即可。</li></ul><p>深入理解Pythonic的几个途径:</p><ul><li>学习语言特性和库特性时,<strong>从官方文档入手,</strong> 仿照他们的书写规范。</li><li>Python的版本更新快,跟进前言,掌握新特性。</li><li>学习业界公认的Pythonic代码,如Flask、gevent和requests等。</li></ul><h1 id="理解Python和C语言的不同之处"><a href="#理解Python和C语言的不同之处" class="headerlink" title="理解Python和C语言的不同之处"></a>理解Python和C语言的不同之处</h1><ul><li><strong>“缩进”和“{}”:</strong> C语言用花括号<code>{}</code>分隔代码块,Python中用缩进分隔,避免混用空格和Tab键。</li><li><strong><code>'</code>与<code>"</code>:</strong> 在C语言中,单引号<code>'</code>表示单个的字符型数据(char),双引号<code>"</code>表示字符串,默认以<code>\0</code>结尾;在Python中,<code>'</code>和<code>"</code>无明显区别。</li><li><strong>三元操作符<code>?:</code>:</strong> C语言中的三元操作符 <code>C?X:Y</code>,表示当条件C为True的时候,取值X,否则取值Y。在Python中的等价形式为 <code>X if C else Y</code>。</li><li><strong>switch…case:</strong> C语言中的<code>switch...case</code>分支语句,Python中可以使用<code>if...elif...else...</code>代替。</li></ul><h1 id="在代码中添加注释"><a href="#在代码中添加注释" class="headerlink" title="在代码中添加注释"></a>在代码中添加注释</h1><p>Python中有3种形式注释:</p><ul><li>块注释</li><li>行注释</li><li>文档注释(dostring)</li></ul><p>需要注意:</p><ol><li>使用块或行注释时,仅仅注释那些复杂操作、算法,还有那些难以理解的、不够一目了然的代码。</li><li>注释和代码隔开一定距离。</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">x = x + <span class="number">1</span> <span class="comment"># 这样的注释略近</span></span><br><span class="line">x = x + <span class="number">1</span> <span class="comment"># 更好的注释位置</span></span><br></pre></td></tr></table></figure><ol><li>给外部可访问的函数或方法添加文档注释。描述其功能、参数、返回值及可能的异常等信息。例如:</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">get_lines</span><span class="params">(name, lines)</span>:</span></span><br><span class="line"> <span class="string">"""Return lines that begin with name.</span></span><br><span class="line"><span class="string"> Lines are expected to look like:</span></span><br><span class="line"><span class="string"> name: space separated values</span></span><br><span class="line"><span class="string"> Args:</span></span><br><span class="line"><span class="string"> name: string, parameter name.</span></span><br><span class="line"><span class="string"> lines: iterable of string, lines in the file.</span></span><br><span class="line"><span class="string"> Returns:</span></span><br><span class="line"><span class="string"> List of values in the lines that match.</span></span><br><span class="line"><span class="string"> """</span></span><br><span class="line"> retval = []</span><br><span class="line"> matches = itertools.ifilter(<span class="keyword">lambda</span> x: x.startswith(name + <span class="string">":"</span>), lines)</span><br><span class="line"> <span class="keyword">for</span> line <span class="keyword">in</span> matches:</span><br><span class="line"> retval.extend(line[len(name) + <span class="number">1</span> :].split())</span><br><span class="line"> <span class="keyword">return</span> retval</span><br></pre></td></tr></table></figure><ol><li>建议在文件头包含copyright声明、模块描述,有必要的话还可以加入作者信息。例如:</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin/python</span></span><br><span class="line"><span class="comment"># -*- coding: utf-8 -*-</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Copyright 2014 Google Inc. All Rights Reserved.</span></span><br><span class="line"><span class="comment">#</span></span><br><span class="line"><span class="comment"># Licensed under the Apache License, Version 2.0 (the "License");</span></span><br><span class="line"><span class="comment"># you may not ...</span></span><br></pre></td></tr></table></figure><ol><li>更新代码之后,注释要和代码同步更新。在实际工作中,很容易发生代码不断迭代,而忘了更新注释的情况,需要加以小心。</li></ol><h1 id="适当添加空行,使代码布局更优雅、合理"><a href="#适当添加空行,使代码布局更优雅、合理" class="headerlink" title="适当添加空行,使代码布局更优雅、合理"></a>适当添加空行,使代码布局更优雅、合理</h1><ol><li>在一组代码表达完一个完整思路之后,应用空行进行分隔。</li><li><strong>保持上下文语义的易理解性。</strong> 当一个函数调用另一个函数时,尽量将它们放在一起,一般<strong>调用者在上,被调用者在下。</strong></li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">A</span><span class="params">()</span>:</span></span><br><span class="line"> B()</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">B</span><span class="params">()</span>:</span></span><br><span class="line"> <span class="keyword">pass</span></span><br></pre></td></tr></table></figure><ol><li><strong>空格的使用</strong><ul><li>二元运算符(赋值<code>=</code>,比较(<code>==, <, >, !=, <=, >=, in, not in, is, is not</code>),布尔运算(<code>and, or, not</code>))的左右两边。如<code>x == 1</code></li><li>逗号和分号前不要使用空格。</li><li>函数名和左括号之间、序列索引操作时序列名和<code>[]</code>之间不需要空格,函数的参数<code>=</code>两侧不需要空格。</li></ul></li></ol><h1 id="编写函数的4个原则"><a href="#编写函数的4个原则" class="headerlink" title="编写函数的4个原则"></a>编写函数的4个原则</h1><ol><li>函数设计尽量短小,嵌套层次不宜过深。</li><li>函数声明需合理、简单、易于使用。</li><li>函数参数设计时,应考虑向下兼容(<strong>兼容之前的版本</strong>)。</li><li>一个函数只做一件事(<strong>解耦合</strong>)。</li></ol><hr><ul><li>参考:《编写高质量代码——改善Python程序的91个建议》</li></ul>]]></content>
<summary type="html">
<blockquote>
<p>本系列文章为《编写高质量代码——改善Python程序的91个建议》的精华汇总。</p>
</blockquote>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>Blender学习资料</title>
<link href="http://monteyang.cn/Blender%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99.html"/>
<id>http://monteyang.cn/Blender%E5%AD%A6%E4%B9%A0%E8%B5%84%E6%96%99.html</id>
<published>2020-03-10T03:51:23.000Z</published>
<updated>2020-03-10T13:15:45.375Z</updated>
<content type="html"><![CDATA[<h1 id="Blender是什么?"><a href="#Blender是什么?" class="headerlink" title="Blender是什么?"></a>Blender是什么?</h1><blockquote><p>摘自官方手册:<br>Blender是一个完整集成的3D创作套件,提供了大量的基础工具,包括<strong>建模、渲染、动画&绑定、视频编辑、视觉效果、合成、贴图,以及多种类型的模拟</strong>。跨平台,使用了OpenGL的GUI可以在所有主流平台上都表现出一致的显示效果(并且<strong>可通过Python脚本来自定义界面</strong>)。高质量的3D架构,带来了快速且高效的工作流。活跃的社区支持, blender.org/community 收录了大量的站点列表。</p></blockquote><a id="more"></a><p>可以看出,Blender的功能很强大,从3D图形到视频,它都能搞。</p><p>博主之前对3D建模软件完全不了解,仅仅是听说过3DMax、Maya这些名字而已。在查阅了一些资料后,发现这种3D建模软件还是适合设计类专业的同学进行系统学习。</p><p>在查资料的过程中,发现这个软件有很多优秀的特点,包括:</p><ul><li><strong>跨平台</strong>: 对Linux用户很友好</li><li><strong>开源</strong>: 基于社区的开源项目,很吊,更新迭代快,完善速度快</li><li><strong>插件</strong>: 可以想象很多大牛会在这搞一些“骚操作”插件</li><li><strong>有Python API</strong>: 这就更骚了,会写代码的话,建模效率岂不是飞起?</li></ul><p>其实博主个人对3D建模、设计什么的不是很感兴趣,所以就学习下基本的操作和Python的调用,也是因为之前师兄说Blender中可以用Python对3D模型处理,之后可能会用得上吧。</p><h1 id="学习资料和社区"><a href="#学习资料和社区" class="headerlink" title="学习资料和社区"></a>学习资料和社区</h1><ul><li><a href="https://www.blendercn.org/" target="_blank" rel="external nofollow noopener noreferrer">Blender中国社区</a>: 国内Blender资料最全的社区。包括视频教程、中文文档、论坛等。</li><li><a href="https://docs.blender.org/manual/zh-hans/dev/index.html" target="_blank" rel="external nofollow noopener noreferrer">Blender 2.83 参考手册</a></li><li><a href="https://docs.blender.org/api/current/index.html" target="_blank" rel="external nofollow noopener noreferrer">Blender 2.82 Python API Documentation</a></li><li><a href="https://www.bilibili.com/video/av17804799/" target="_blank" rel="external nofollow noopener noreferrer">Blender官方入门教程(中文)B站</a>: 每个视频极短,适合小白入门,</li></ul><h1 id="常用快捷键"><a href="#常用快捷键" class="headerlink" title="常用快捷键"></a>常用快捷键</h1><p>众所周知,无论是玩什么软件,掌握快捷键都能<strong>极大程度地提高工作效率</strong>。</p><h2 id="通用操作"><a href="#通用操作" class="headerlink" title="通用操作"></a>通用操作</h2><ul><li>停止当前操作:【ESC】</li><li>快捷搜索:【SPACE】</li><li>撤销:【Ctrl】+【z】</li><li>重做:【Ctrl】+【shift】+【z】</li><li>渲染:【F12】</li><li>单选:【鼠标右键】(RMB)</li><li>全选:【A】</li><li>框选:【B】</li><li>刷选:【C】</li><li>套选:【Ctrl】+【鼠标左键】(LMB)</li><li>删除:【X】/【Delete】</li><li>复制:【Shift】+【D】</li><li>添加:【Shift】+【A】</li><li>取消:【Esc】/【RMB】</li><li>确认:【Return】/【LMB】</li></ul><h2 id="界面操作"><a href="#界面操作" class="headerlink" title="界面操作"></a>界面操作</h2><ul><li>工具栏位置对称切换:【F5】</li><li>固定/解固定工具栏:【SHIFT】+【LMB】</li><li>放大/缩小:【SHIFT】+【SPACE】</li><li>放大/缩小:【Ctrl】+【UP】/【Ctrl】+【DOWN】</li><li>移动视窗:【SHIFT】+【鼠标滚轮】</li><li>旋转视窗:【鼠标滚轮】</li><li>3DView:【SHIFT】+【F5】</li><li>UVEditorView:【SHIFT】+【F10】</li></ul><h2 id="小键盘"><a href="#小键盘" class="headerlink" title="小键盘"></a>小键盘</h2><ul><li>透视开启/关闭:【5】</li><li>前视图(+Ctrl后视图):【1】</li><li>右视图(+Ctrl左视图):【2】</li><li>顶视图(+Ctrl底视图):【7】</li><li>摄像机视角(如果有摄像机):【0】</li><li>将当前视图设为摄像机视角:【Ctrl】+【alt】+【0】</li><li>全屏显示当前视图:【Ctrl】+【up】</li><li>显示选中目标:小键盘【del】</li><li>显示所有目标:【Home】</li><li>场景平移:【Shift】+【鼠标中键】</li><li>场景缩放:【Ctrl】+【鼠标中键】(或者【滚轮】)</li></ul><h2 id="建模"><a href="#建模" class="headerlink" title="建模"></a>建模</h2><ul><li>编辑模式:【Tab】</li><li>点线面三模式切换(编辑模式下):【Tab】+【Ctrl】</li><li>加选/减选:【Ctrl】+【小键盘+/-】(可定义为【PageUP】,【PageDown】)</li><li>选择循环点/边/面:【Alt】+【LMB】</li><li>线框模式:【Z】</li><li>隐藏选中目标:【H】</li><li>显示所有隐藏目标:【Alt】+【H】</li></ul><h2 id="选中目标状态下"><a href="#选中目标状态下" class="headerlink" title="选中目标状态下"></a>选中目标状态下</h2><ul><li>挤出:【E】+【LMB】(挤出到鼠标位置)</li><li>移动:【G】</li><li>旋转:【R】</li><li>缩放:【S】(以上操作再按下X、Y、Z以固定轴向、轴心活动)</li><li>内插面:【i】</li><li>顶点/边滑移:【GG】</li><li>环切:【Ctrl】+【R】</li><li>边线折痕:【Shift】+【E】</li><li>快捷拓展命令栏:【W】</li><li>切割:【K】</li><li>分割:【Y】</li><li>分离(单独个体):【P】</li><li>合并:【Ctrl】+【J】</li><li>倒角:【Ctrl】+【B】</li><li>球形化:【Shift】+【Alt】+【S】</li><li>关联选取:【L】</li><li>相似选取:【Shift】+【G】</li><li>创建父级:【Ctrl】+【P】</li><li>清除父级:【Alt】+【P】</li><li>吸附:【Shift】+【S】</li></ul><h2 id="节点编辑器"><a href="#节点编辑器" class="headerlink" title="节点编辑器"></a>节点编辑器</h2><ul><li>连接节点:【F】(选取两个目标)</li><li>断开节点:【Ctrl】+【LMB】(划掉连接线)</li><li>添加转接点:【Shift】+【LMB】(划掉连接线)</li><li>合并节点:【Ctrl】+【J】</li><li>断开选中节点:【Alt】+【D】</li><li>移动背景视图:【Alt】+【鼠标滚轮】</li><li>显示激活节点:小键盘【del】</li><li>显示所有节点:【Home】</li></ul><h2 id="动画"><a href="#动画" class="headerlink" title="动画"></a>动画</h2><ul><li>删除动画关键帧在信息清单视图:(DopeSheet)中按【B】框选按【X】删除选中的keyframes</li><li>插入一个关键帧(keyframe):【I】</li><li>清除该关键帧:【Alt】-【I】</li><li>清空所有关键帧(删除所有的F-Curves):【Alt】-【Shift】-【I】</li><li>assignadriver:【D】</li><li>clearthedriver:【Alt】-【D】</li><li>addaKeyingSet:【K】</li><li>cleartheKeyingSet:【Alt】-【K】</li><li>清除posemode下的旋转:【Alt】+【R】</li><li>清除posemode下的缩放:【Alt】+【S】</li><li>清楚posemode下的位移:【Alt】+【G】</li></ul><h2 id="文本编辑"><a href="#文本编辑" class="headerlink" title="文本编辑"></a>文本编辑</h2><ul><li>到文本开始处:【Home】</li><li>到文本结束处:【End】</li><li>拷贝文本:【Ctrl】-【C】</li><li>粘贴文本:【Ctrl】-【V】</li><li>选择所有文本:【Ctrl】-【A】</li></ul><h2 id="数字调整"><a href="#数字调整" class="headerlink" title="数字调整"></a>数字调整</h2><ul><li>拖动时捕捉离散步骤:【Ctrl】</li><li>更高的调整精度:【Shift】</li></ul><h2 id="补充"><a href="#补充" class="headerlink" title="补充"></a>补充</h2><ul><li>编辑模式下,弹出边编辑菜单,其中有UV映射常用的seem(缝边)功能:【Ctrl】+【E】</li><li>合并物体:【Ctrl】+【J】</li><li>分离物体:【P】</li><li>把选中的两个相邻三角形合并成四边形(quads):【ALT】+【J】</li><li>吸附游标到选择点:【SHIFT】+【S】</li><li>撕开所选边:【V】</li><li>撕开所选边并填充:【ALT】+【V】</li><li>编辑模式下,合并选中的2个节点:【ALT】+【M】</li><li>打开吸附模式:【SHIFT】+【TAB】</li><li>打开点线面选择模式选取菜单:【Ctrl】+【TAB】</li><li>在EditMode下,将选中的表面变成三角面:【Ctrl】+【T】</li><li>环切loopcut:【Ctrl】+【R】</li><li>多个环切:【再按住鼠标滚轮上下滚动】</li></ul>]]></content>
<summary type="html">
<h1 id="Blender是什么?"><a href="#Blender是什么?" class="headerlink" title="Blender是什么?"></a>Blender是什么?</h1><blockquote>
<p>摘自官方手册:<br>Blender是一个完整集成的3D创作套件,提供了大量的基础工具,包括<strong>建模、渲染、动画&amp;绑定、视频编辑、视觉效果、合成、贴图,以及多种类型的模拟</strong>。跨平台,使用了OpenGL的GUI可以在所有主流平台上都表现出一致的显示效果(并且<strong>可通过Python脚本来自定义界面</strong>)。高质量的3D架构,带来了快速且高效的工作流。活跃的社区支持, blender.org/community 收录了大量的站点列表。</p>
</blockquote>
</summary>
<category term="软件" scheme="http://monteyang.cn/categories/%E8%BD%AF%E4%BB%B6/"/>
<category term="Blender" scheme="http://monteyang.cn/tags/Blender/"/>
</entry>
<entry>
<title>Python-for循环的内部机制</title>
<link href="http://monteyang.cn/Python-for%E5%BE%AA%E7%8E%AF%E7%9A%84%E5%86%85%E9%83%A8%E6%9C%BA%E5%88%B6.html"/>
<id>http://monteyang.cn/Python-for%E5%BE%AA%E7%8E%AF%E7%9A%84%E5%86%85%E9%83%A8%E6%9C%BA%E5%88%B6.html</id>
<published>2020-03-02T06:36:24.000Z</published>
<updated>2020-03-31T08:23:05.631Z</updated>
<content type="html"><![CDATA[<p>Python中,使用for循环可以迭代容器对象中的元素,这里容器对象包括是列表(list)、元组(tuple)、字典(dict)、集合(set)等。但是,为什么这些对象可以使用for循环进行操作呢?</p><a id="more"></a><p>首先,定义一个简单的类尝试一下:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestRange</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, num)</span>:</span></span><br><span class="line"> self.num = num</span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> TestRange(<span class="number">10</span>):</span><br><span class="line"> print(i)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出</span></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">TypeError: <span class="string">'TestRange'</span> object <span class="keyword">is</span> <span class="keyword">not</span> iterable</span><br></pre></td></tr></table></figure></p><p>错误信息提示,’TestRange’ object 不是可迭代的对象。那么,什么才是可迭代的对象呢?</p><p>在可迭代的对象中,需要实现一个<code>__iter__</code>魔法方法,而且这个方法的返回值需要是一个迭代器。那么,什么是迭代器呢?</p><p>迭代器只需要实现<code>__next__</code>魔法方法。</p><p>以列表(list)为例:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>nums = [<span class="number">13</span>,<span class="number">12</span>,<span class="number">33</span>]</span><br><span class="line"><span class="meta">>>> </span>iter_ret = nums.__iter__() <span class="comment"># x有此方法,说明list是可迭代的,而且该方法返回一个迭代器</span></span><br><span class="line"><span class="meta">>>> </span>iter_ret</span><br><span class="line"><list_iterator object at <span class="number">0x100f32198</span>></span><br><span class="line"></span><br><span class="line"><span class="meta">>>> </span>iter_ret.__next__()</span><br><span class="line"><span class="number">13</span></span><br><span class="line"><span class="meta">>>> </span>iter_ret.__next__()</span><br><span class="line"><span class="number">12</span></span><br><span class="line"><span class="meta">>>> </span>iter_ret.__next__()</span><br><span class="line"><span class="number">33</span></span><br><span class="line"><span class="meta">>>> </span>iter_ret.__next__()</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<stdin>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">StopIteration</span><br></pre></td></tr></table></figure><blockquote><p><strong>分析:</strong></p><p>如上所示,列表nums中实现了<code>__iter__</code>方法,而且返回一个迭代器(iterator),迭代器中实现了<code>__next__</code>方法。在不断调用<code>__next__</code>的过程中,就是在不断返回nums中的元素,直到出现<code>StopIteration</code>的错误。</p></blockquote><p>其实,for语句的作用与此类似。<strong>for语句的内部机制为</strong>:</p><ul><li>先判断对象是否为可迭代对象,即是否存在<code>__iter__</code>方法,如果存在则调用<code>__iter__</code>方法,返回一个迭代器;否则,直接抛出TypeError异常;</li><li>不断地调用迭代器的<code>__next__</code>方法,每次调用按顺序迭代获取当前的值;</li><li>迭代完所有元素,就抛出异常 StopIteration,这个异常 python 解释器自己会处理;</li></ul><p>前面的 TestRange 报错是因为它没有实现迭代器协议里面的这两个方法,现在继续改进:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestRange</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self, _max)</span>:</span></span><br><span class="line"> self.i = <span class="number">0</span></span><br><span class="line"> self._max = _max</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__iter__</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">return</span> self</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__next__</span><span class="params">(self)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> self.i < self._max:</span><br><span class="line"> i = self.i</span><br><span class="line"> self.i += <span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> i</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> <span class="comment"># 达到停止条件时,抛出此异常</span></span><br><span class="line"> <span class="keyword">raise</span> StopIteration()</span><br><span class="line"></span><br><span class="line"><span class="comment"># 进行测试</span></span><br><span class="line"><span class="keyword">for</span> i <span class="keyword">in</span> TestRange(<span class="number">3</span>):</span><br><span class="line"> print(i)</span><br><span class="line"><span class="comment"># 输出</span></span><br><span class="line"> <span class="number">0</span></span><br><span class="line"> <span class="number">1</span></span><br><span class="line"> <span class="number">2</span></span><br></pre></td></tr></table></figure><blockquote><p><strong>分析:</strong></p><p>因为这个类中,已经实现了<code>__next__</code>方法,所以基于这个类所创建的对象,本身就是一个迭代器。又因为可迭代对象需要有<code>__iter__</code>方法,而且返回一个迭代器,所以<code>__iter__</code>返回对象本身<code>self</code>即可。</p></blockquote>]]></content>
<summary type="html">
<p>Python中,使用for循环可以迭代容器对象中的元素,这里容器对象包括是列表(list)、元组(tuple)、字典(dict)、集合(set)等。但是,为什么这些对象可以使用for循环进行操作呢?</p>
</summary>
<category term="Python" scheme="http://monteyang.cn/categories/Python/"/>
<category term="Python" scheme="http://monteyang.cn/tags/Python/"/>
</entry>
<entry>
<title>机器学习-决策树</title>
<link href="http://monteyang.cn/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%86%B3%E7%AD%96%E6%A0%91.html"/>
<id>http://monteyang.cn/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%86%B3%E7%AD%96%E6%A0%91.html</id>
<published>2020-02-22T06:49:11.000Z</published>
<updated>2020-03-05T12:20:34.682Z</updated>
<content type="html"><![CDATA[<p><img data-src="../images/机器学习-决策树.png" alt></p><hr><a id="more"></a><h1 id="决策树模型"><a href="#决策树模型" class="headerlink" title="决策树模型"></a>决策树模型</h1><p>从根节点开始,在每一个节点进行决策,最终走到叶子节点。既可以做<strong>分类</strong>,也可以做<strong>回归</strong>。</p><p>优点:可读性强,分类速度快。</p><p>通常,决策树学习分为三步: <strong>特征选择</strong>、<strong>决策树生成(构建)</strong>和<strong>决策树的剪枝</strong>。</p><blockquote><p><strong>难点在于决策树的构建</strong>。当构建好决策树后,利用其进行测试,对数据进行分类或回归都是十分简单的。</p></blockquote><h1 id="树的组成"><a href="#树的组成" class="headerlink" title="树的组成"></a>树的组成</h1><ul><li>根节点: 第一个判断条件的节点</li><li>非叶子结点: 中间的过程</li><li>叶子节点: 得到最终的决策结果</li></ul><p>决策树中的每个节点(特征)相当于在数据中切一刀,如果候选的特征越多,切的次数越多。</p><h1 id="决策树生成"><a href="#决策树生成" class="headerlink" title="决策树生成"></a>决策树生成</h1><p>决策树的训练过程就是<strong>决策树的生成</strong>,从给定数据集,构造出一课树。</p><p>从根节点开始选择特征,考虑如何进行特征切分。</p><blockquote><p>从根节点到下面的节点,如何进行选择和切分?</p></blockquote><p>思路: 从根节点到下面的节点所对应的特征,应该依次是从分类效果最好到不好。</p><p>因此,目标: 通过一种衡量标准,计算不同特征进行分支选择后的分类情况,衡量特征的分类效果,找出最好的特征当作根节点,以此类推。</p><h2 id="熵"><a href="#熵" class="headerlink" title="熵"></a>熵</h2><p>熵:<strong>表示随机变量不确定性的度量。不确定性越强,熵值越高</strong>。</p><p>假设 $X$ 是一个具有有限个值的离散型随机变量,服从如下的概率分布:</p><script type="math/tex; mode=display">P(X=x_i)=p_i,\qquad i=1,2,\cdots,n</script><p>则,随机变量$X$的熵定义为:</p><script type="math/tex; mode=display">H(X)=-\sum_{i=1}^np_i log p_i \quad (2)</script><p>假设 X 服从如下分布:</p><script type="math/tex; mode=display">P(X=1)=p,P(X=0)=1-p,0 \le p \le 1</script><p>于是根据 <strong>公式(2)</strong> 得到它的熵为:</p><script type="math/tex; mode=display">H(p)=-p\log_2p-(1-p)\log_2(1-p)</script><p><img data-src="../images/机器学习-决策树-熵.png" alt></p><p>概率和熵值大小的关系:</p><ul><li>当 p=0或1 时,H(p)=0,随机变量没有不确定性</li><li>当 p=0.5 时,H(p)=1,随机变量的不确定性最大</li></ul><h2 id="信息增益"><a href="#信息增益" class="headerlink" title="信息增益"></a>信息增益</h2><p>设随机变量 $(X,Y)$ 的<strong>联合概率分布</strong>为:</p><script type="math/tex; mode=display">P(X=x_i,Y=y_j)=p_{ij},\quad i=1,2,\cdots,n;\quad j=1,2,\cdots ,m</script><p><strong>条件熵 $H(Y|X)$</strong> 表示在已知随机变量 $X$ 的取值条件下,随机变量 $Y$ 的不确定性。</p><p>其数学定义为:$X$ 给定的条件下 $Y$ 的条件概率分布的熵对 $X$ 的数学期望,</p><script type="math/tex; mode=display">H(Y|X)=\sum_{i=1}^np_iH(Y|X=x_i)</script><p>其中,$p_i=P(X=x_i),\quad i=1,2,\cdots,n$</p><p>在此基础上,引出<strong>信息增益</strong>(Information Gain),它<strong>表示在特征 $X$ 给定的条件下,而使得类 $Y$ 的信息不确定性减少的程度</strong>。数学精确表述如下:特征 $A$ 对训练数据集 $D$ 的<strong>信息增益 $G(D,A)$</strong> 定义为集合 $D$ 的熵 $H(D)$ 与特征 $A$ 给定的条件下 $D$ 的条件熵 $H(D | A)$ 之差,即:</p><script type="math/tex; mode=display">G(D,A)=H(D)-H(D|A)</script><p>决策树学习应用信息增益准则选择特征。给定训练数据集 $D$ 和特征 $A$。熵 $H(D)$ 表示对数据集 $D$ 进行分类的不确定性,而条件熵 $H(D|A)$ 表示在特征 $A$ 给定的条件下对数据集 $D$ 进行分类的不确定性。而他们的差,即信息增益就表示由于特征 $A$ 给定的情况下而使得对数据集 $D$ 进行分类的不确定性减少的程度。显然,对于数据集 $D$ 而言,信息增益依赖于特征。一般情况下,不同的特征具有不同的信息增益。<strong>信息增益大的特征具有更强的分类能力。</strong></p><p>由以上的表述,我们应该清楚地知道,决策树构建过程中,我们应该选择信息增益最大的特征进行分裂构建。</p><h2 id="ID3"><a href="#ID3" class="headerlink" title="ID3"></a>ID3</h2><p>ID3算法的核心是递归的构建决策树,递归的过程中,在每个节点上,计算信息增益选择特征,直至满足递归停止条件(所有特征的信息增益都很小或者没有特征可以选择)。</p><h2 id="C4-5"><a href="#C4-5" class="headerlink" title="C4.5"></a>C4.5</h2><p>C4.5 算法和 ID3 算法基本上完全一致,只是特征选择时的选择方法将信息增益换成<strong>信息增益比</strong>。</p><blockquote><p><strong>信息增益比</strong>:<br>特征 $A$ 对训练数据集 $D$ 的信息增益比 $G_R(D,A)$ 表示特征 $A$ 的信息增益 $G(D,A)$ 与训练数据集 $D$ 关于特征 $A$ 的熵 $H_A(D)$ 的比值,即:</p><script type="math/tex; mode=display">G_R(D,A)=\frac{G(D,A)}{H_A(D)}</script></blockquote><hr><h1 id="决策树的剪枝"><a href="#决策树的剪枝" class="headerlink" title="决策树的剪枝"></a>决策树的剪枝</h1><p>决策树过拟合风险很大,理论上可以完全分开(极限情况:每个数据对应一个叶子结点)</p><h2 id="预剪枝"><a href="#预剪枝" class="headerlink" title="预剪枝"></a>预剪枝</h2><p>在构建决策树的过程中,进行剪枝,预剪枝的方法包括:</p><ul><li>限制树的<strong>深度</strong></li><li>限制<strong>叶子结点的个数</strong></li><li>限制<strong>叶子结点的样本数</strong></li><li>限制<strong>信息增益</strong></li></ul><h2 id="后剪枝"><a href="#后剪枝" class="headerlink" title="后剪枝"></a>后剪枝</h2><p>后剪枝指的是,建立树之后,再进行剪枝。<br>通过一定的衡量标准,衡量是否分裂该结点。</p><p>总体思路为:</p><p>由完全树 T0 开始,剪枝部分结点得到 T1,再次剪枝部分结点得到 T2……直到剩下树根的树 Tk;在验证数据集上对这 k 个树分别评价,选择损失函数最小的树 Ta。</p>]]></content>
<summary type="html">
<p><img data-src="../images/机器学习-决策树.png" alt></p>
<hr>
</summary>
<category term="机器学习" scheme="http://monteyang.cn/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
<category term="机器学习" scheme="http://monteyang.cn/tags/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
</entry>
<entry>
<title>LeetCode-41-50题</title>
<link href="http://monteyang.cn/LeetCode-41-50%E9%A2%98.html"/>
<id>http://monteyang.cn/LeetCode-41-50%E9%A2%98.html</id>
<published>2020-02-11T05:24:11.000Z</published>
<updated>2020-02-22T04:54:20.620Z</updated>
<content type="html"><![CDATA[<blockquote><p>leetcode 41~50 题</p></blockquote><a id="more"></a><h1 id="41-缺失的第一个正数"><a href="#41-缺失的第一个正数" class="headerlink" title="41. 缺失的第一个正数"></a>41. 缺失的第一个正数</h1><p>给定一个未排序的整数数组,找出其中没有出现的最小的正整数。</p><p>示例 1:</p><pre><code>输入: [1,2,0]输出: 3</code></pre><p>示例 2:</p><pre><code>输入: [3,4,-1,1]输出: 2</code></pre><p>示例 3:</p><pre><code>输入: [7,8,9,11,12]输出: 1</code></pre><p>说明:</p><ul><li>你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">firstMissingPositive</span><span class="params">(self, nums: List[int])</span> -> int:</span></span><br><span class="line"> _nums = [<span class="number">-1</span>] * len(nums)</span><br><span class="line"> <span class="keyword">for</span> n <span class="keyword">in</span> nums:</span><br><span class="line"> <span class="keyword">if</span> n <= <span class="number">0</span> <span class="keyword">or</span> n > len(nums):</span><br><span class="line"> <span class="keyword">continue</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> _nums[n<span class="number">-1</span>] = n</span><br><span class="line"></span><br><span class="line"> <span class="keyword">for</span> i, num <span class="keyword">in</span> enumerate(_nums):</span><br><span class="line"> <span class="keyword">if</span> num != i+<span class="number">1</span>:</span><br><span class="line"> <span class="keyword">return</span> i+<span class="number">1</span></span><br><span class="line"> <span class="keyword">return</span> len(nums)+<span class="number">1</span></span><br></pre></td></tr></table></figure><hr><h1 id="42-接雨水"><a href="#42-接雨水" class="headerlink" title="42. 接雨水"></a>42. 接雨水</h1><p>给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。</p><p><img data-src="https://assets.leetcode-cn.com/aliyun-lc-upload/uploads/2018/10/22/rainwatertrap.png" alt></p><p>上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。</p><p>示例:</p><pre><code>输入: [0,1,0,2,1,0,1,3,2,1,2,1]输出: 6</code></pre><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">trap</span><span class="params">(self, height: List[int])</span> -> int:</span></span><br><span class="line"> water_sum = <span class="number">0</span></span><br><span class="line"> left_max_height = <span class="number">0</span></span><br><span class="line"> <span class="comment"># 遍历从 idx=1 到 idx=leng(height)-2</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, len(height) - <span class="number">1</span>):</span><br><span class="line"> <span class="comment"># 求左边最高的墙高</span></span><br><span class="line"> left_max_height = height[i - <span class="number">1</span>] \</span><br><span class="line"> <span class="keyword">if</span> height[i - <span class="number">1</span>] > left_max_height <span class="keyword">else</span> left_max_height</span><br><span class="line"> <span class="comment"># 求右边最高的墙高</span></span><br><span class="line"> right_max_height = <span class="number">0</span></span><br><span class="line"> right_max_height = max(height[i+<span class="number">1</span>:])</span><br><span class="line"> <span class="comment"># 当前列可容纳的水量</span></span><br><span class="line"> water = max(min(left_max_height, right_max_height) - height[i], <span class="number">0</span>)</span><br><span class="line"> water_sum += water</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> water_sum</span><br></pre></td></tr></table></figure><hr><h1 id="43-字符串相乘"><a href="#43-字符串相乘" class="headerlink" title="43. 字符串相乘"></a>43. 字符串相乘</h1><p>给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。</p><p>示例 1:</p><pre><code>输入: num1 = "2", num2 = "3"输出: "6"</code></pre><p>示例 2:</p><pre><code>输入: num1 = "123", num2 = "456"输出: "56088"</code></pre><p>说明:</p><ul><li>num1 和 num2 的长度小于110。</li><li>num1 和 num2 只包含数字 0-9。</li><li>num1 和 num2 均不以零开头,除非是数字 0 本身。</li><li>不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">__init__</span><span class="params">(self)</span>:</span></span><br><span class="line"> self._dict = {}</span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">10</span>):</span><br><span class="line"> self._dict.update({str(i): i})</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">multiply</span><span class="params">(self, num1: str, num2: str)</span> -> str:</span></span><br><span class="line"> <span class="comment"># 使num1为长度较小的</span></span><br><span class="line"> <span class="keyword">if</span> len(num1) > len(num2):</span><br><span class="line"> num1, num2 = num2, num1</span><br><span class="line"> num2 = self.str2int(num2)</span><br><span class="line"> <span class="comment"># 将num1的每一位与num2相乘</span></span><br><span class="line"> res = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, len(num1)+<span class="number">1</span>):</span><br><span class="line"> res += self._dict[num1[-i]] * num2 * (<span class="number">10</span>**(i<span class="number">-1</span>))</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> str(res)</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">str2int</span><span class="params">(self, num)</span>:</span></span><br><span class="line"> <span class="string">"""将str类型转化为int类型"""</span></span><br><span class="line"> ret = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, len(num)+<span class="number">1</span>):</span><br><span class="line"> ret += self._dict[num[-i]] * (<span class="number">10</span>**(i<span class="number">-1</span>))</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> ret</span><br></pre></td></tr></table></figure><hr><h1 id="44-TODO"><a href="#44-TODO" class="headerlink" title="44. TODO"></a>44. TODO</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h1 id="45-跳跃游戏-II"><a href="#45-跳跃游戏-II" class="headerlink" title="45. 跳跃游戏 II"></a>45. 跳跃游戏 II</h1><p>给定一个非负整数数组,你最初位于数组的第一个位置。</p><p>数组中的每个元素代表你在该位置可以跳跃的最大长度。</p><p>你的目标是使用最少的跳跃次数到达数组的最后一个位置。</p><p>示例:</p><pre><code>输入: [2,3,1,1,4]输出: 2解释: 跳到最后一个位置的最小跳跃数是 2。 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。</code></pre><p>说明:</p><pre><code>假设你总是可以到达数组的最后一个位置。</code></pre><blockquote><p>思路:考虑贪心算法,如何确定下一步的位置?考虑下下一步能够到的最远距离。</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">jump</span><span class="params">(self, nums: List[int])</span> -> int:</span></span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">util</span><span class="params">(idx)</span>:</span></span><br><span class="line"> <span class="string">"""输入当前idx, 返回当前应走到的索引"""</span></span><br><span class="line"> max_distance = <span class="number">0</span></span><br><span class="line"> go2idx = <span class="number">0</span></span><br><span class="line"> <span class="comment"># 遍历当前可以走的所有索引</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(<span class="number">1</span>, nums[idx]+<span class="number">1</span>):</span><br><span class="line"> next_idx = idx + i <span class="comment"># 下一位置的索引</span></span><br><span class="line"> <span class="keyword">if</span> next_idx >= len(nums) - <span class="number">1</span>:</span><br><span class="line"> <span class="keyword">return</span> len(nums) - <span class="number">1</span></span><br><span class="line"> distance = next_idx + nums[next_idx] <span class="comment"># 可以走的距离</span></span><br><span class="line"> <span class="keyword">if</span> distance > max_distance:</span><br><span class="line"> max_distance = distance</span><br><span class="line"> go2idx = next_idx</span><br><span class="line"> <span class="keyword">return</span> go2idx</span><br><span class="line"></span><br><span class="line"> next_idx = <span class="number">0</span></span><br><span class="line"> i = <span class="number">0</span></span><br><span class="line"> <span class="keyword">while</span> next_idx < len(nums)<span class="number">-1</span>:</span><br><span class="line"> next_idx = util(next_idx)</span><br><span class="line"> i += <span class="number">1</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> i</span><br></pre></td></tr></table></figure><hr><h1 id="46-全排列"><a href="#46-全排列" class="headerlink" title="46. 全排列"></a>46. 全排列</h1><p>给定一个没有重复数字的序列,返回其所有可能的全排列。</p><p>示例:</p><pre><code>输入: [1,2,3]输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]</code></pre><blockquote><p>思路:用树结构思考,考虑深度优先遍历</p></blockquote><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> copy</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Solution</span>:</span></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">permute</span><span class="params">(self, nums: List[int])</span> -> List[List[int]]:</span></span><br><span class="line"> res = []</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">def</span> <span class="title">dfs</span><span class="params">(mem, residual)</span>:</span></span><br><span class="line"> <span class="comment"># 如果没有剩余元素,直接返回</span></span><br><span class="line"> <span class="keyword">if</span> <span class="keyword">not</span> residual:</span><br><span class="line"> res.append(mem)</span><br><span class="line"> <span class="keyword">return</span></span><br><span class="line"> <span class="keyword">for</span> i <span class="keyword">in</span> range(len(residual)):</span><br><span class="line"> residual_tmp = copy.deepcopy(residual)</span><br><span class="line"> residual_tmp.pop(i)</span><br><span class="line"> dfs(mem+[residual[i]], residual_tmp)</span><br><span class="line"></span><br><span class="line"> dfs([], nums)</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> res</span><br></pre></td></tr></table></figure><hr><h1 id="47-TODO"><a href="#47-TODO" class="headerlink" title="47. TODO"></a>47. TODO</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h1 id="48-TODO"><a href="#48-TODO" class="headerlink" title="48. TODO"></a>48. TODO</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h1 id="49-TODO"><a href="#49-TODO" class="headerlink" title="49. TODO"></a>49. TODO</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><hr><h1 id="50-TODO"><a href="#50-TODO" class="headerlink" title="50. TODO"></a>50. TODO</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<blockquote>
<p>leetcode 41~50 题</p>
</blockquote>
</summary>
<category term="LeetCode" scheme="http://monteyang.cn/categories/LeetCode/"/>
<category term="LeetCode" scheme="http://monteyang.cn/tags/LeetCode/"/>
</entry>
<entry>
<title>论文阅读-PointNet</title>
<link href="http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-PointNet.html"/>
<id>http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-PointNet.html</id>
<published>2020-01-09T06:56:01.000Z</published>
<updated>2020-02-18T15:22:56.179Z</updated>
<content type="html"><![CDATA[<h2 id="PointNet-Deep-Learning-on-Point-Sets-for-3D-Classification-and-Segmentation"><a href="#PointNet-Deep-Learning-on-Point-Sets-for-3D-Classification-and-Segmentation" class="headerlink" title="PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation"></a>PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation</h2><ul><li>关键词: point cloud, deep learning</li><li>源码: √</li></ul><a id="more"></a><h2 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h2><h3 id="1-Plroblem"><a href="#1-Plroblem" class="headerlink" title="1. Plroblem"></a>1. Plroblem</h3><ul><li>直接对点云进行学习 => 实现分类/分割</li></ul><ul><li>针对点云的深度学习算法需满足的特性:<ul><li><strong>无序性</strong>: 所有点无次序</li><li><strong>点与点之间的关系</strong>: 点与neighbor之间存在局部的结构关系</li><li><strong>变换下的不变性</strong>: 旋转/平移等不改变点云模型的整体类别和局部分割类别</li></ul></li></ul><h3 id="2-Method"><a href="#2-Method" class="headerlink" title="2. Method"></a>2. Method</h3><ul><li>提取点云的全局/局部特征<ul><li>全局特征: 表示形状类别的特征</li><li>局部特征: 每个点的特征</li></ul></li></ul><ul><li>T-Net: 将所有点对齐到一个规范空间中</li><li>用<strong>对称函数</strong> MaxPooling: 解决点云的无序性</li><li>对于Segmentation: 局部特征 + 全局特征 (Aggregation)</li></ul><h4 id="Network-Structure"><a href="#Network-Structure" class="headerlink" title="Network Structure"></a>Network Structure</h4><p><img data-src="/images/PointNet-Network.png" alt="Network" title="PointNet"></p><ul><li>输入的点数为 n</li><li>global feature 维度1024不是对应点数,而是模型整体的特征</li></ul><h3 id="3-Experiment"><a href="#3-Experiment" class="headerlink" title="3. Experiment"></a>3. Experiment</h3><h4 id="3-1-Dataset"><a href="#3-1-Dataset" class="headerlink" title="3.1 Dataset"></a>3.1 Dataset</h4><ul><li>3D分类: ModelNet40</li><li>3D部件分割: ShapeNet的子集(16类)</li><li>3D场景分割: I. Armeni, O. Sener, A. R. Zamir, H. Jiang, I. Brilakis,M. Fischer, and S. Savarese. 3d semantic parsing of large-scale indoor spaces.</li></ul><h4 id="3-2-Implemention"><a href="#3-2-Implemention" class="headerlink" title="3.2 Implemention"></a>3.2 Implemention</h4><ul><li>数据预处理<ul><li>在Mesh的表面均匀采样1024个点</li></ul></li></ul><h4 id="3-3-Metric"><a href="#3-3-Metric" class="headerlink" title="3.3 Metric"></a>3.3 Metric</h4><ul><li>3D 分类:<ul><li>accuracy</li></ul></li><li>3D 分割:<ul><li>mIoU</li></ul></li></ul><h3 id="4-Disadvantages"><a href="#4-Disadvantages" class="headerlink" title="4. Disadvantages"></a>4. Disadvantages</h3><p>未充分挖掘局部结构特征</p>]]></content>
<summary type="html">
<h2 id="PointNet-Deep-Learning-on-Point-Sets-for-3D-Classification-and-Segmentation"><a href="#PointNet-Deep-Learning-on-Point-Sets-for-3D-Classification-and-Segmentation" class="headerlink" title="PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation"></a>PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation</h2><ul>
<li>关键词: point cloud, deep learning</li>
<li>源码: √</li>
</ul>
</summary>
<category term="论文阅读" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
<category term="笔记" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/%E7%AC%94%E8%AE%B0/"/>
<category term="论文阅读" scheme="http://monteyang.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
</entry>
<entry>
<title>论文阅读-VoxNet</title>
<link href="http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-VoxNet.html"/>
<id>http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-VoxNet.html</id>
<published>2020-01-09T06:38:39.000Z</published>
<updated>2020-02-18T15:22:56.179Z</updated>
<content type="html"><![CDATA[<h2 id="VoxNet-A-3D-Convolutional-Neural-Network-for-Real-Time-Object-Recognition"><a href="#VoxNet-A-3D-Convolutional-Neural-Network-for-Real-Time-Object-Recognition" class="headerlink" title="VoxNet: A 3D Convolutional Neural Network for Real-Time Object Recognition"></a>VoxNet: A 3D Convolutional Neural Network for Real-Time Object Recognition</h2><ul><li>关键词: voxel, 3D deep learning</li><li>会议: IROS</li><li>源码: official √<ul><li><a href="https://github.com/MonteYang/VoxNet.pytorch" target="_blank" rel="external nofollow noopener noreferrer">我的复现: by PyTorch</a></li></ul></li></ul><a id="more"></a><h2 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h2><h3 id="1-Plroblem"><a href="#1-Plroblem" class="headerlink" title="1. Plroblem"></a>1. Plroblem</h3><p>针对Voxel的3d物体识别/分类</p><h3 id="2-Method"><a href="#2-Method" class="headerlink" title="2. Method"></a>2. Method</h3><p>将在视频领域取得一定效果的3D CNN用于Voxel的特征提取</p><h4 id="Network-Structure"><a href="#Network-Structure" class="headerlink" title="Network Structure"></a>Network Structure</h4><p><img data-src="/images/3-VoxNet-Network.png" alt title="VoxNet-Network"></p><h3 id="3-Experiment"><a href="#3-Experiment" class="headerlink" title="3. Experiment"></a>3. Experiment</h3><h4 id="3-1-Dataset"><a href="#3-1-Dataset" class="headerlink" title="3.1 Dataset"></a>3.1 Dataset</h4><p>3种数据集:</p><ul><li>LiDAR data - Sydney Urban Objects</li><li>CAD data - ModelNet</li><li>RGBD data - NYUv2</li></ul><h4 id="3-2-Implemention"><a href="#3-2-Implemention" class="headerlink" title="3.2 Implemention"></a>3.2 Implemention</h4><p>TODO:</p><h3 id="4-Advantages"><a href="#4-Advantages" class="headerlink" title="4. Advantages"></a>4. Advantages</h3><ul><li>表现性能超过了之前的 ShapeNet</li><li>参数比 ShapeNet 少一些 <blockquote><p>ShapeNet is a relatively large architecture, with over 12.4 million parameters, while VoxNet has less than 1 million.</p></blockquote></li></ul><h3 id="5-Disadvantages"><a href="#5-Disadvantages" class="headerlink" title="5. Disadvantages"></a>5. Disadvantages</h3><ul><li>计算性能受Voxel的分辨率限制: 当Voxel分辨率过高时,内存占用过高</li></ul>]]></content>
<summary type="html">
<h2 id="VoxNet-A-3D-Convolutional-Neural-Network-for-Real-Time-Object-Recognition"><a href="#VoxNet-A-3D-Convolutional-Neural-Network-for-Real-Time-Object-Recognition" class="headerlink" title="VoxNet: A 3D Convolutional Neural Network for Real-Time Object Recognition"></a>VoxNet: A 3D Convolutional Neural Network for Real-Time Object Recognition</h2><ul>
<li>关键词: voxel, 3D deep learning</li>
<li>会议: IROS</li>
<li>源码: official √<ul>
<li><a href="https://github.com/MonteYang/VoxNet.pytorch" target="_blank" rel="external nofollow noopener noreferrer">我的复现: by PyTorch</a></li>
</ul>
</li>
</ul>
</summary>
<category term="论文阅读" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
<category term="笔记" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/%E7%AC%94%E8%AE%B0/"/>
<category term="论文阅读" scheme="http://monteyang.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
<category term="Voxel" scheme="http://monteyang.cn/tags/Voxel/"/>
</entry>
<entry>
<title>论文阅读-Ciss-Net</title>
<link href="http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-Ciss-Net.html"/>
<id>http://monteyang.cn/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB-Ciss-Net.html</id>
<published>2020-01-09T06:28:22.000Z</published>
<updated>2020-03-11T13:18:23.711Z</updated>
<content type="html"><![CDATA[<h2 id="Context-Reinforced-Semantic-Segmentation"><a href="#Context-Reinforced-Semantic-Segmentation" class="headerlink" title="Context-Reinforced Semantic Segmentation"></a><a href="http://openaccess.thecvf.com/content_CVPR_2019/papers/Zhou_Context-Reinforced_Semantic_Segmentation_CVPR_2019_paper.pdf" target="_blank" rel="external nofollow noopener noreferrer">Context-Reinforced Semantic Segmentation</a></h2><ul><li>关键词: 强化学习, image segmentation, context</li><li>会议: CVPR 2019</li><li>源码: √</li></ul><a id="more"></a><h2 id="Note"><a href="#Note" class="headerlink" title="Note"></a>Note</h2><h3 id="1-Plroblem"><a href="#1-Plroblem" class="headerlink" title="1. Plroblem"></a>1. Plroblem</h3><ul><li>Context(上下文信息)在语义分割中至关重要, 挖掘图像中上下文信息</li></ul><h3 id="2-Method"><a href="#2-Method" class="headerlink" title="2. Method"></a>2. Method</h3><ul><li>使用分割后的图片 p-maps 作为上下文信息的来源</li><li>该项工作提出Context-Net -> 更好的挖掘上下文信息</li><li>将上下文信息的学习过程定义为马尔科夫决策问题(MDP), 使用强化学习方法进行优化</li></ul><h4 id="Network-Structure"><a href="#Network-Structure" class="headerlink" title="Network Structure"></a>Network Structure</h4><p><img data-src="/images/CissNet-Network.png" alt="Ciss_Net"></p><ul><li>Environment: <code>p-map</code></li><li>Agent: <code>Context Net</code><ul><li>State: $\{Y_I\}$</li><li>Action: $\{B_I\}$</li></ul></li></ul><h3 id="3-Experiment"><a href="#3-Experiment" class="headerlink" title="3. Experiment"></a>3. Experiment</h3><h4 id="3-1-Dataset"><a href="#3-1-Dataset" class="headerlink" title="3.1 Dataset"></a>3.1 Dataset</h4><ul><li>ADE20K</li><li>Cityscapes</li><li>Pascal Context</li></ul><h4 id="3-2-Implemention"><a href="#3-2-Implemention" class="headerlink" title="3.2 Implemention"></a>3.2 Implemention</h4><p>TODO</p><h4 id="3-3-Metric"><a href="#3-3-Metric" class="headerlink" title="3.3 Metric"></a>3.3 Metric</h4><h4 id="3-4-Ablation-Study"><a href="#3-4-Ablation-Study" class="headerlink" title="3.4 Ablation Study"></a>3.4 Ablation Study</h4><h4 id="3-5-Result"><a href="#3-5-Result" class="headerlink" title="3.5 Result"></a>3.5 Result</h4><!-- ### 4. Advantages ### 5. Disadvantages -->]]></content>
<summary type="html">
<h2 id="Context-Reinforced-Semantic-Segmentation"><a href="#Context-Reinforced-Semantic-Segmentation" class="headerlink" title="Context-Reinforced Semantic Segmentation"></a><a href="http://openaccess.thecvf.com/content_CVPR_2019/papers/Zhou_Context-Reinforced_Semantic_Segmentation_CVPR_2019_paper.pdf" target="_blank" rel="external nofollow noopener noreferrer">Context-Reinforced Semantic Segmentation</a></h2><ul>
<li>关键词: 强化学习, image segmentation, context</li>
<li>会议: CVPR 2019</li>
<li>源码: √</li>
</ul>
</summary>
<category term="论文阅读" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
<category term="笔记" scheme="http://monteyang.cn/categories/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/%E7%AC%94%E8%AE%B0/"/>
<category term="强化学习" scheme="http://monteyang.cn/tags/%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0/"/>
<category term="论文阅读" scheme="http://monteyang.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
<category term="image segmentation" scheme="http://monteyang.cn/tags/image-segmentation/"/>
</entry>
</feed>