forked from sixu05202004/pythontutorial3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstdlib2.html
More file actions
571 lines (482 loc) · 58.2 KB
/
stdlib2.html
File metadata and controls
571 lines (482 loc) · 58.2 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
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>11. 标准库浏览 – Part II — Python tutorial 3.5.2 documentation</title>
<link href='https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic|Roboto+Slab:400,700|Inconsolata:400,700&subset=latin,cyrillic' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="top" title="Python tutorial 3.5.2 documentation" href="index.html"/>
<link rel="next" title="12. 虚拟环境和包" href="venv.html"/>
<link rel="prev" title="10. Python 标准库概览" href="stdlib.html"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.6.2/modernizr.min.js"></script>
</head>
<body class="wy-body-for-nav" role="document">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-nav-search">
<a href="index.html" class="fa fa-home"> Python tutorial</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="appetite.html">1. 开胃菜</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter.html">2. 使用 Python 解释器</a><ul>
<li class="toctree-l2"><a class="reference internal" href="interpreter.html#tut-invoking">2.1. 调用 Python 解释器</a></li>
<li class="toctree-l2"><a class="reference internal" href="interpreter.html#tut-interp">2.2. 解释器及其环境</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="introduction.html">3. Python 简介</a><ul>
<li class="toctree-l2"><a class="reference internal" href="introduction.html#tut-calculator">3.1. 将 Python 当做计算器</a></li>
<li class="toctree-l2"><a class="reference internal" href="introduction.html#tut-firststeps">3.2. 编程的第一步</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="controlflow.html">4. 深入 Python 流程控制</a><ul>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#if">4.1. if 语句</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#for">4.2. for 语句</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#range">4.3. range() 函数</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#break-continue-else">4.4. break 和 continue 语句, 以及循环中的 else 子句</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#pass">4.5. pass 语句</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#tut-functions">4.6. 定义函数</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#tut-defining">4.7. 深入 Python 函数定义</a></li>
<li class="toctree-l2"><a class="reference internal" href="controlflow.html#tut-codingstyle">4.8. 插曲:编码风格</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="datastructures.html">5. 数据结构</a><ul>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-morelists">5.1. 关于列表更多的内容</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#del">5.2. del 语句</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-tuples">5.3. 元组和序列</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-sets">5.4. 集合</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-dictionaries">5.5. 字典</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-loopidioms">5.6. 循环技巧</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-conditions">5.7. 深入条件控制</a></li>
<li class="toctree-l2"><a class="reference internal" href="datastructures.html#tut-comparing">5.8. 比较序列和其它类型</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">6. 模块</a><ul>
<li class="toctree-l2"><a class="reference internal" href="modules.html#tut-moremodules">6.1. 深入模块</a></li>
<li class="toctree-l2"><a class="reference internal" href="modules.html#tut-standardmodules">6.2. 标准模块</a></li>
<li class="toctree-l2"><a class="reference internal" href="modules.html#dir">6.3. dir() 函数</a></li>
<li class="toctree-l2"><a class="reference internal" href="modules.html#tut-packages">6.4. 包</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="inputoutput.html">7. 输入和输出</a><ul>
<li class="toctree-l2"><a class="reference internal" href="inputoutput.html#tut-formatting">7.1. 格式化输出</a></li>
<li class="toctree-l2"><a class="reference internal" href="inputoutput.html#tut-files">7.2. 文件读写</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="errors.html">8. 错误和异常</a><ul>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-syntaxerrors">8.1. 语法错误</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-exceptions">8.2. 异常</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-handling">8.3. 异常处理</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-raising">8.4. 抛出异常</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-userexceptions">8.5. 用户自定义异常</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-cleanup">8.6. 定义清理行为</a></li>
<li class="toctree-l2"><a class="reference internal" href="errors.html#tut-cleanup-with">8.7. 预定义清理行为</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="classes.html">9. 类</a><ul>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-object">9.1. 术语相关</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#python">9.2. Python 作用域和命名空间</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-firstclasses">9.3. 初识类</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-remarks">9.4. 一些说明</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-inheritance">9.5. 继承</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-private">9.6. 私有变量</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-odds">9.7. 补充</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-exceptionclasses">9.8. 异常也是类</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-iterators">9.9. 迭代器</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-generators">9.10. 生成器</a></li>
<li class="toctree-l2"><a class="reference internal" href="classes.html#tut-genexps">9.11. 生成器表达式</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="stdlib.html">10. Python 标准库概览</a><ul>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-os-interface">10.1. 操作系统接口</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-file-wildcards">10.2. 文件通配符</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-command-line-arguments">10.3. 命令行参数</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-stderr">10.4. 错误输出重定向和程序终止</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-string-pattern-matching">10.5. 字符串正则匹配</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-mathematics">10.6. 数学</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-internet-access">10.7. 互联网访问</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-dates-and-times">10.8. 日期和时间</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-data-compression">10.9. 数据压缩</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-performance-measurement">10.10. 性能度量</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-quality-control">10.11. 质量控制</a></li>
<li class="toctree-l2"><a class="reference internal" href="stdlib.html#tut-batteries-included">10.12. “瑞士军刀”</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">11. 标准库浏览 – Part II</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#tut-output-formatting">11.1. 输出格式</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-templating">11.2. 模板</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-binary-formats">11.3. 使用二进制数据记录布局</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-multi-threading">11.4. 多线程</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-logging">11.5. 日志</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-weak-references">11.6. 弱引用</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-list-tools">11.7. 列表工具</a></li>
<li class="toctree-l2"><a class="reference internal" href="#tut-decimal-fp">11.8. 十进制浮点数算法</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="venv.html">12. 虚拟环境和包</a><ul>
<li class="toctree-l2"><a class="reference internal" href="venv.html#id2">12.1. 简介</a></li>
<li class="toctree-l2"><a class="reference internal" href="venv.html#id4">12.2. 创建虚拟环境</a></li>
<li class="toctree-l2"><a class="reference internal" href="venv.html#pip">12.3. 使用 pip 管理包</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="whatnow.html">13. 接下来?</a></li>
<li class="toctree-l1"><a class="reference internal" href="interactive.html">14. 交互式输入行编辑历史回溯</a><ul>
<li class="toctree-l2"><a class="reference internal" href="interactive.html#tab">14.1. Tab 补全和历史记录</a></li>
<li class="toctree-l2"><a class="reference internal" href="interactive.html#tut-commentary">14.2. 其它交互式解释器</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="floatingpoint.html">15. 浮点数算法:争议和限制</a><ul>
<li class="toctree-l2"><a class="reference internal" href="floatingpoint.html#tut-fp-error">15.1. 表达错误</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="appendix.html">16. 附录</a><ul>
<li class="toctree-l2"><a class="reference internal" href="appendix.html#tut-interac">16.1. 交互模式</a></li>
</ul>
</li>
</ul>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">Python tutorial</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html">Docs</a> »</li>
<li>11. 标准库浏览 – Part II</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/stdlib2.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document">
<div class="section" id="part-ii">
<span id="tut-brieftourtwo"></span><h1>11. 标准库浏览 – Part II<a class="headerlink" href="#part-ii" title="Permalink to this headline">¶</a></h1>
<p>第二部分包含了支持专业编程工作所需的更高级的模块,这些模块很少出现在小脚本中。</p>
<div class="section" id="tut-output-formatting">
<span id="id1"></span><h2>11.1. 输出格式<a class="headerlink" href="#tut-output-formatting" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://docs.python.org/3/library/reprlib.html#module-reprlib">reprlib</a> 模块为大型的或深度嵌套的容器缩写显示提供了 :<a class="reference external" href="https://docs.python.org/3/library/functions.html#repr">repr()</a> 函数的一个定制版本:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">reprlib</span>
<span class="gp">>>> </span><span class="n">reprlib</span><span class="o">.</span><span class="n">repr</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="s1">'supercalifragilisticexpialidocious'</span><span class="p">))</span>
<span class="go">"set(['a', 'c', 'd', 'e', 'f', 'g', ...])"</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/pprint.html#module-pprint">pprint</a> 模块给老手提供了一种解释器可读的方式深入控制内置和用户自定义对象的打印。当输出超过一行的时候,“美化打印(pretty printer)”添加断行和标识符,使得数据结构显示的更清晰:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">pprint</span>
<span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="p">[[[[</span><span class="s1">'black'</span><span class="p">,</span> <span class="s1">'cyan'</span><span class="p">],</span> <span class="s1">'white'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'green'</span><span class="p">,</span> <span class="s1">'red'</span><span class="p">]],</span> <span class="p">[[</span><span class="s1">'magenta'</span><span class="p">,</span>
<span class="gp">... </span> <span class="s1">'yellow'</span><span class="p">],</span> <span class="s1">'blue'</span><span class="p">]]]</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
<span class="go">[[[['black', 'cyan'],</span>
<span class="go"> 'white',</span>
<span class="go"> ['green', 'red']],</span>
<span class="go"> [['magenta', 'yellow'],</span>
<span class="go"> 'blue']]]</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/textwrap.html#module-textwrap">textwrap</a> 模块格式化文本段落以适应设定的屏宽:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">textwrap</span>
<span class="gp">>>> </span><span class="n">doc</span> <span class="o">=</span> <span class="s2">"""The wrap() method is just like fill() except that it returns</span>
<span class="gp">... </span><span class="s2">a list of strings instead of one big string with newlines to separate</span>
<span class="gp">... </span><span class="s2">the wrapped lines."""</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">textwrap</span><span class="o">.</span><span class="n">fill</span><span class="p">(</span><span class="n">doc</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mi">40</span><span class="p">))</span>
<span class="go">The wrap() method is just like fill()</span>
<span class="go">except that it returns a list of strings</span>
<span class="go">instead of one big string with newlines</span>
<span class="go">to separate the wrapped lines.</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/locale.html#module-locale">locale</a> 模块按访问预定好的国家信息数据库。locale 的格式化函数属性集提供了一个直接方式以分组标示格式化数字:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">locale</span>
<span class="gp">>>> </span><span class="n">locale</span><span class="o">.</span><span class="n">setlocale</span><span class="p">(</span><span class="n">locale</span><span class="o">.</span><span class="n">LC_ALL</span><span class="p">,</span> <span class="s1">'English_United States.1252'</span><span class="p">)</span>
<span class="go">'English_United States.1252'</span>
<span class="gp">>>> </span><span class="n">conv</span> <span class="o">=</span> <span class="n">locale</span><span class="o">.</span><span class="n">localeconv</span><span class="p">()</span> <span class="c1"># get a mapping of conventions</span>
<span class="gp">>>> </span><span class="n">x</span> <span class="o">=</span> <span class="mf">1234567.8</span>
<span class="gp">>>> </span><span class="n">locale</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="s2">"</span><span class="si">%d</span><span class="s2">"</span><span class="p">,</span> <span class="n">x</span><span class="p">,</span> <span class="n">grouping</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">'1,234,567'</span>
<span class="gp">>>> </span><span class="n">locale</span><span class="o">.</span><span class="n">format_string</span><span class="p">(</span><span class="s2">"</span><span class="si">%s%.*f</span><span class="s2">"</span><span class="p">,</span> <span class="p">(</span><span class="n">conv</span><span class="p">[</span><span class="s1">'currency_symbol'</span><span class="p">],</span>
<span class="gp">... </span> <span class="n">conv</span><span class="p">[</span><span class="s1">'frac_digits'</span><span class="p">],</span> <span class="n">x</span><span class="p">),</span> <span class="n">grouping</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">'$1,234,567.80'</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-templating">
<span id="id2"></span><h2>11.2. 模板<a class="headerlink" href="#tut-templating" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://docs.python.org/3/library/string.html#module-string">string</a> 提供了一个灵活多变的模版类 <a class="reference external" href="https://docs.python.org/3/library/string.html#string.Template">Template</a> ,使用它最终用户可以用简单的进行编辑。这使用户可以在不进行改变的情况下定制他们的应用程序。</p>
<p>格式使用 <code class="docutils literal"><span class="pre">$</span></code> 为开头的 Python 合法标识(数字、字母和下划线)作为占位符。占位符外面的大括号使它可以和其它的字符不加空格混在一起。 <code class="docutils literal"><span class="pre">$$</span></code> 创建一个单独的 <code class="docutils literal"><span class="pre">$</span></code>:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">string</span> <span class="k">import</span> <span class="n">Template</span>
<span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="s1">'$</span><span class="si">{village}</span><span class="s1">folk send $$10 to $cause.'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">t</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">village</span><span class="o">=</span><span class="s1">'Nottingham'</span><span class="p">,</span> <span class="n">cause</span><span class="o">=</span><span class="s1">'the ditch fund'</span><span class="p">)</span>
<span class="go">'Nottinghamfolk send $10 to the ditch fund.'</span>
</pre></div>
</div>
<p>当一个占位符在字典或关键字参数中没有被提供时,<a class="reference external" href="https://docs.python.org/3/library/string.html#string.Template.substitute">substitute()</a> 方法就会抛出一个 <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#KeyError">KeyError</a> 异常。 对于邮件合并风格的应用程序,用户提供的数据可能并不完整,这时使用 <a class="reference external" href="https://docs.python.org/3/library/string.html#string.Template.safe_substitute">safe_substitute()</a> 方法可能更适合 — 如果数据不完整,它就不会改变占位符:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="n">Template</span><span class="p">(</span><span class="s1">'Return the $item to $owner.'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">d</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">(</span><span class="n">item</span><span class="o">=</span><span class="s1">'unladen swallow'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">t</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="c">...</span>
<span class="gr">KeyError</span>: <span class="n">'owner'</span>
<span class="gp">>>> </span><span class="n">t</span><span class="o">.</span><span class="n">safe_substitute</span><span class="p">(</span><span class="n">d</span><span class="p">)</span>
<span class="go">'Return the unladen swallow to $owner.'</span>
</pre></div>
</div>
<p>模板子类可以指定一个自定义分隔符。例如,图像查看器的批量重命名工具可能选择使用百分号作为占位符,像当前日期,图片序列号或文件格式:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">time</span><span class="o">,</span> <span class="nn">os.path</span>
<span class="gp">>>> </span><span class="n">photofiles</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'img_1074.jpg'</span><span class="p">,</span> <span class="s1">'img_1076.jpg'</span><span class="p">,</span> <span class="s1">'img_1077.jpg'</span><span class="p">]</span>
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">BatchRename</span><span class="p">(</span><span class="n">Template</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">delimiter</span> <span class="o">=</span> <span class="s1">'%'</span>
<span class="gp">>>> </span><span class="n">fmt</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'Enter rename style (</span><span class="si">%d</span><span class="s1">-date %n-seqnum </span><span class="si">%f</span><span class="s1">-format): '</span><span class="p">)</span>
<span class="go">Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f</span>
<span class="gp">>>> </span><span class="n">t</span> <span class="o">=</span> <span class="n">BatchRename</span><span class="p">(</span><span class="n">fmt</span><span class="p">)</span>
<span class="gp">>>> </span><span class="n">date</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'</span><span class="si">%d</span><span class="s1">%b%y'</span><span class="p">)</span>
<span class="gp">>>> </span><span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">filename</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">photofiles</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">base</span><span class="p">,</span> <span class="n">ext</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">splitext</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="gp">... </span> <span class="n">newname</span> <span class="o">=</span> <span class="n">t</span><span class="o">.</span><span class="n">substitute</span><span class="p">(</span><span class="n">d</span><span class="o">=</span><span class="n">date</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">f</span><span class="o">=</span><span class="n">ext</span><span class="p">)</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">'</span><span class="si">{0}</span><span class="s1"> --> </span><span class="si">{1}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="n">newname</span><span class="p">))</span>
<span class="go">img_1074.jpg --> Ashley_0.jpg</span>
<span class="go">img_1076.jpg --> Ashley_1.jpg</span>
<span class="go">img_1077.jpg --> Ashley_2.jpg</span>
</pre></div>
</div>
<p>模板的另一个应用是把多样的输出格式细节从程序逻辑中分类出来。这便使得 XML 文件,纯文本报表和 HTML WEB 报表定制模板成为可能。</p>
</div>
<div class="section" id="tut-binary-formats">
<span id="id3"></span><h2>11.3. 使用二进制数据记录布局<a class="headerlink" href="#tut-binary-formats" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://docs.python.org/3/library/struct.html#module-struct">struct</a> 模块为使用变长的二进制记录格式提供了 <a class="reference external" href="https://docs.python.org/3/library/struct.html#struct.pack">pack()</a> 和 <a class="reference external" href="https://docs.python.org/3/library/struct.html#struct.unpack">unpack()</a> 函数。下面的示例演示了在不使用 <a class="reference external" href="https://docs.python.org/3/library/zipfile.html#module-zipfile">zipfile</a> 模块的情况下如何迭代一个 ZIP 文件的头信息。压缩码 <code class="docutils literal"><span class="pre">"H"</span></code> 和 <code class="docutils literal"><span class="pre">"I"</span></code> 分别表示2和4字节无符号数字, <code class="docutils literal"><span class="pre">"<"</span></code> 表明它们都是标准大小并且按照 little-endian 字节排序。</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">struct</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'myfile.zip'</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
<span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span> <span class="c1"># show the first 3 file headers</span>
<span class="n">start</span> <span class="o">+=</span> <span class="mi">14</span>
<span class="n">fields</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">unpack</span><span class="p">(</span><span class="s1">'<IIIHH'</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="mi">16</span><span class="p">])</span>
<span class="n">crc32</span><span class="p">,</span> <span class="n">comp_size</span><span class="p">,</span> <span class="n">uncomp_size</span><span class="p">,</span> <span class="n">filenamesize</span><span class="p">,</span> <span class="n">extra_size</span> <span class="o">=</span> <span class="n">fields</span>
<span class="n">start</span> <span class="o">+=</span> <span class="mi">16</span>
<span class="n">filename</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="n">filenamesize</span><span class="p">]</span>
<span class="n">start</span> <span class="o">+=</span> <span class="n">filenamesize</span>
<span class="n">extra</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">start</span><span class="o">+</span><span class="n">extra_size</span><span class="p">]</span>
<span class="nb">print</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="nb">hex</span><span class="p">(</span><span class="n">crc32</span><span class="p">),</span> <span class="n">comp_size</span><span class="p">,</span> <span class="n">uncomp_size</span><span class="p">)</span>
<span class="n">start</span> <span class="o">+=</span> <span class="n">extra_size</span> <span class="o">+</span> <span class="n">comp_size</span> <span class="c1"># skip to the next header</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-multi-threading">
<span id="id4"></span><h2>11.4. 多线程<a class="headerlink" href="#tut-multi-threading" title="Permalink to this headline">¶</a></h2>
<p>线程是一个分离无顺序依赖关系任务的技术。在某些任务运行于后台的时候应用程序会变得迟缓,线程可以提升其速度。一个有关的用途是在 I/O 的同时其它线程可以并行计算。</p>
<p>下面的代码显示了高级模块 <a class="reference external" href="https://docs.python.org/3/library/threading.html#module-threading">threading</a> 如何在主程序运行的同时运行任务:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">threading</span><span class="o">,</span> <span class="nn">zipfile</span>
<span class="k">class</span> <span class="nc">AsyncZip</span><span class="p">(</span><span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">infile</span><span class="p">,</span> <span class="n">outfile</span><span class="p">):</span>
<span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">infile</span> <span class="o">=</span> <span class="n">infile</span>
<span class="bp">self</span><span class="o">.</span><span class="n">outfile</span> <span class="o">=</span> <span class="n">outfile</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">zipfile</span><span class="o">.</span><span class="n">ZipFile</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">outfile</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">,</span> <span class="n">zipfile</span><span class="o">.</span><span class="n">ZIP_DEFLATED</span><span class="p">)</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">infile</span><span class="p">)</span>
<span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Finished background zip of:'</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">infile</span><span class="p">)</span>
<span class="n">background</span> <span class="o">=</span> <span class="n">AsyncZip</span><span class="p">(</span><span class="s1">'mydata.txt'</span><span class="p">,</span> <span class="s1">'myarchive.zip'</span><span class="p">)</span>
<span class="n">background</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'The main program continues to run in foreground.'</span><span class="p">)</span>
<span class="n">background</span><span class="o">.</span><span class="n">join</span><span class="p">()</span> <span class="c1"># Wait for the background task to finish</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'Main program waited until background was done.'</span><span class="p">)</span>
</pre></div>
</div>
<p>多线程应用程序的主要挑战是协调线程,诸如线程间共享数据或其它资源。为了达到那个目的,线程模块提供了许多同步化的原生支持,包括:锁,事件,条件变量和信号灯。</p>
<p>尽管这些工具很强大,微小的设计错误也可能造成难以挽回的故障。因此,任务协调的首选方法是把对一个资源的所有访问集中在一个单独的线程中,然后使用 <a class="reference external" href="https://docs.python.org/3/library/queue.html#module-queue">queue</a> 模块用那个线程服务其他线程的请求。为内部线程通信和协调而使用 <a class="reference external" href="https://docs.python.org/3/library/queue.html#queue.Queue">Queue</a> 对象的应用程序更易于设计,更可读,并且更可靠。</p>
</div>
<div class="section" id="tut-logging">
<span id="id6"></span><h2>11.5. 日志<a class="headerlink" href="#tut-logging" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://docs.python.org/3/library/logging.html#module-logging">logging</a> 模块提供了完整和灵活的日志系统。它最简单的用法是记录信息并发送到一个文件或 <code class="docutils literal"><span class="pre">sys.stderr</span></code>:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s1">'Debugging information'</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'Informational message'</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="s1">'Warning:config file </span><span class="si">%s</span><span class="s1"> not found'</span><span class="p">,</span> <span class="s1">'server.conf'</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s1">'Error occurred'</span><span class="p">)</span>
<span class="n">logging</span><span class="o">.</span><span class="n">critical</span><span class="p">(</span><span class="s1">'Critical error -- shutting down'</span><span class="p">)</span>
</pre></div>
</div>
<p>输出如下:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">WARNING</span><span class="p">:</span><span class="n">root</span><span class="p">:</span><span class="ne">Warning</span><span class="p">:</span><span class="n">config</span> <span class="n">file</span> <span class="n">server</span><span class="o">.</span><span class="n">conf</span> <span class="ow">not</span> <span class="n">found</span>
<span class="n">ERROR</span><span class="p">:</span><span class="n">root</span><span class="p">:</span><span class="n">Error</span> <span class="n">occurred</span>
<span class="n">CRITICAL</span><span class="p">:</span><span class="n">root</span><span class="p">:</span><span class="n">Critical</span> <span class="n">error</span> <span class="o">--</span> <span class="n">shutting</span> <span class="n">down</span>
</pre></div>
</div>
<p>默认情况下捕获信息和调试消息并将输出发送到标准错误流。其它可选的路由信息方式通过 email,数据报文,socket 或者 HTTP Server。基于消息属性,新的过滤器可以选择不同的路由: <code class="xref py py-const docutils literal"><span class="pre">DEBUG</span></code>, <code class="xref py py-const docutils literal"><span class="pre">INFO</span></code>,
<code class="xref py py-const docutils literal"><span class="pre">WARNING</span></code>, <code class="xref py py-const docutils literal"><span class="pre">ERROR</span></code> 和 <code class="xref py py-const docutils literal"><span class="pre">CRITICAL</span></code> 。</p>
<p>日志系统可以直接在 Python 代码中定制,也可以不经过应用程序直接在一个用户可编辑的配置文件中加载。</p>
</div>
<div class="section" id="tut-weak-references">
<span id="id7"></span><h2>11.6. 弱引用<a class="headerlink" href="#tut-weak-references" title="Permalink to this headline">¶</a></h2>
<p>Python 自动进行内存管理(对大多数的对象进行引用计数和垃圾回收—— <a class="reference external" href="https://docs.python.org/3/glossary.html#term-garbage-collection">垃圾回收</a> ——以循环利用)在最后一个引用消失后,内存会很快释放。</p>
<p>这个工作方式对大多数应用程序工作良好,但是偶尔会需要跟踪对象来做一些事。不幸的是,仅仅为跟踪它们创建引用也会使其长期存在。 <a class="reference external" href="https://docs.python.org/3/library/weakref.html#module-weakref">weakref</a> 模块提供了不用创建引用的跟踪对象工具,一旦对象不再存在,它自动从弱引用表上删除并触发回调。典型的应用包括捕获难以构造的对象:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">weakref</span><span class="o">,</span> <span class="nn">gc</span>
<span class="gp">>>> </span><span class="k">class</span> <span class="nc">A</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="gp">... </span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">A</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># create a reference</span>
<span class="gp">>>> </span><span class="n">d</span> <span class="o">=</span> <span class="n">weakref</span><span class="o">.</span><span class="n">WeakValueDictionary</span><span class="p">()</span>
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'primary'</span><span class="p">]</span> <span class="o">=</span> <span class="n">a</span> <span class="c1"># does not create a reference</span>
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'primary'</span><span class="p">]</span> <span class="c1"># fetch the object if it is still alive</span>
<span class="go">10</span>
<span class="gp">>>> </span><span class="k">del</span> <span class="n">a</span> <span class="c1"># remove the one reference</span>
<span class="gp">>>> </span><span class="n">gc</span><span class="o">.</span><span class="n">collect</span><span class="p">()</span> <span class="c1"># run garbage collection right away</span>
<span class="go">0</span>
<span class="gp">>>> </span><span class="n">d</span><span class="p">[</span><span class="s1">'primary'</span><span class="p">]</span> <span class="c1"># entry was automatically removed</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">"<stdin>"</span>, line <span class="m">1</span>, in <span class="n"><module></span>
<span class="n">d</span><span class="p">[</span><span class="s1">'primary'</span><span class="p">]</span> <span class="c1"># entry was automatically removed</span>
File <span class="nb">"C:/python34/lib/weakref.py"</span>, line <span class="m">46</span>, in <span class="n">__getitem__</span>
<span class="n">o</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">key</span><span class="p">]()</span>
<span class="gr">KeyError</span>: <span class="n">'primary'</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-list-tools">
<span id="id9"></span><h2>11.7. 列表工具<a class="headerlink" href="#tut-list-tools" title="Permalink to this headline">¶</a></h2>
<p>很多数据结构可能会用到内置列表类型。然而,有时可能需要不同性能代价的实现。</p>
<p><a class="reference external" href="https://docs.python.org/3/library/array.html#module-array">array</a> 模块提供了一个类似列表的 <a class="reference external" href="https://docs.python.org/3/library/array.html#array.array">array()</a> 对象,它仅仅是存储数据,更为紧凑。以下的示例演示了一个存储双字节无符号整数的数组(类型编码 <code class="docutils literal"><span class="pre">"H"</span></code> )而非存储 16 字节 Python 整数对象的普通正规列表:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">array</span> <span class="k">import</span> <span class="n">array</span>
<span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="n">array</span><span class="p">(</span><span class="s1">'H'</span><span class="p">,</span> <span class="p">[</span><span class="mi">4000</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">700</span><span class="p">,</span> <span class="mi">22222</span><span class="p">])</span>
<span class="gp">>>> </span><span class="nb">sum</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
<span class="go">26932</span>
<span class="gp">>>> </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span>
<span class="go">array('H', [10, 700])</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/collections.html#module-collections">collections</a> 模块提供了类似列表的 <a class="reference external" href="https://docs.python.org/3/library/collections.html#collections.deque">deque()</a> 对象,它从左边添加(append)和弹出(pop)更快,但是在内部查询更慢。这些对象更适用于队列实现和广度优先的树搜索:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">collections</span> <span class="k">import</span> <span class="n">deque</span>
<span class="gp">>>> </span><span class="n">d</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="s2">"task1"</span><span class="p">,</span> <span class="s2">"task2"</span><span class="p">,</span> <span class="s2">"task3"</span><span class="p">])</span>
<span class="gp">>>> </span><span class="n">d</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">"task4"</span><span class="p">)</span>
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="s2">"Handling"</span><span class="p">,</span> <span class="n">d</span><span class="o">.</span><span class="n">popleft</span><span class="p">())</span>
<span class="go">Handling task1</span>
</pre></div>
</div>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">unsearched</span> <span class="o">=</span> <span class="n">deque</span><span class="p">([</span><span class="n">starting_node</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">breadth_first_search</span><span class="p">(</span><span class="n">unsearched</span><span class="p">):</span>
<span class="n">node</span> <span class="o">=</span> <span class="n">unsearched</span><span class="o">.</span><span class="n">popleft</span><span class="p">()</span>
<span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">gen_moves</span><span class="p">(</span><span class="n">node</span><span class="p">):</span>
<span class="k">if</span> <span class="n">is_goal</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
<span class="k">return</span> <span class="n">m</span>
<span class="n">unsearched</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
</pre></div>
</div>
<p>除了链表的替代实现,该库还提供了 <a class="reference external" href="https://docs.python.org/3/library/bisect.html#module-bisect">bisect</a> 这样的模块以操作存储链表:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">bisect</span>
<span class="gp">>>> </span><span class="n">scores</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">100</span><span class="p">,</span> <span class="s1">'perl'</span><span class="p">),</span> <span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="s1">'tcl'</span><span class="p">),</span> <span class="p">(</span><span class="mi">400</span><span class="p">,</span> <span class="s1">'lua'</span><span class="p">),</span> <span class="p">(</span><span class="mi">500</span><span class="p">,</span> <span class="s1">'python'</span><span class="p">)]</span>
<span class="gp">>>> </span><span class="n">bisect</span><span class="o">.</span><span class="n">insort</span><span class="p">(</span><span class="n">scores</span><span class="p">,</span> <span class="p">(</span><span class="mi">300</span><span class="p">,</span> <span class="s1">'ruby'</span><span class="p">))</span>
<span class="gp">>>> </span><span class="n">scores</span>
<span class="go">[(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/heapq.html#module-heapq">heapq</a> 提供了基于正规链表的堆实现。最小的值总是保持在 0 点。这在希望循环访问最小元素但是不想执行完整堆排序的时候非常有用:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">heapq</span> <span class="k">import</span> <span class="n">heapify</span><span class="p">,</span> <span class="n">heappop</span><span class="p">,</span> <span class="n">heappush</span>
<span class="gp">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>
<span class="gp">>>> </span><span class="n">heapify</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="c1"># rearrange the list into heap order</span>
<span class="gp">>>> </span><span class="n">heappush</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># add a new entry</span>
<span class="gp">>>> </span><span class="p">[</span><span class="n">heappop</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">)]</span> <span class="c1"># fetch the three smallest entries</span>
<span class="go">[-5, 0, 1]</span>
</pre></div>
</div>
</div>
<div class="section" id="tut-decimal-fp">
<span id="id11"></span><h2>11.8. 十进制浮点数算法<a class="headerlink" href="#tut-decimal-fp" title="Permalink to this headline">¶</a></h2>
<p><a class="reference external" href="https://docs.python.org/3/library/decimal.html#module-decimal">decimal</a> 模块提供了一个 <a class="reference external" href="https://docs.python.org/3/library/decimal.html#decimal.Decimal">Decimal</a> 数据类型用于浮点数计算。相比内置的二进制浮点数实现 <a class="reference external" href="https://docs.python.org/3/library/functions.html#float">float</a>,这个类型有助于</p>
<ul>
<li><p class="first">金融应用和其它需要精确十进制表达的场合,</p>
</li>
<li><p class="first">控制精度,</p>
</li>
<li><p class="first">控制舍入以适应法律或者规定要求,</p>
</li>
<li><p class="first">确保十进制数位精度,</p>
<p>或者</p>
</li>
<li><p class="first">用户希望计算结果与手算相符的场合。</p>
</li>
</ul>
<p>例如,计算 70 分电话费的 5% 税计算,十进制浮点数和二进制浮点数计算结果的差别如下。如果在分值上舍入,这个差别就很重要了:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">from</span> <span class="nn">decimal</span> <span class="k">import</span> <span class="o">*</span>
<span class="gp">>>> </span><span class="nb">round</span><span class="p">(</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">'0.70'</span><span class="p">)</span> <span class="o">*</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">'1.05'</span><span class="p">),</span> <span class="mi">2</span><span class="p">)</span>
<span class="go">Decimal('0.74')</span>
<span class="gp">>>> </span><span class="nb">round</span><span class="p">(</span><span class="o">.</span><span class="mi">70</span> <span class="o">*</span> <span class="mf">1.05</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="go">0.73</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/decimal.html#decimal.Decimal">Decimal</a> 的结果总是保有结尾的 0,自动从两位精度延伸到4位。Decimal 重现了手工的数学运算,这就确保了二进制浮点数无法精确保有的数据精度。</p>
<p>高精度使 <a class="reference external" href="https://docs.python.org/3/library/decimal.html#decimal.Decimal">Decimal</a> 可以执行二进制浮点数无法进行的模运算和等值测试:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Decimal</span><span class="p">(</span><span class="s1">'1.00'</span><span class="p">)</span> <span class="o">%</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">'.10'</span><span class="p">)</span>
<span class="go">Decimal('0.00')</span>
<span class="gp">>>> </span><span class="mf">1.00</span> <span class="o">%</span> <span class="mf">0.10</span>
<span class="go">0.09999999999999995</span>
<span class="gp">>>> </span><span class="nb">sum</span><span class="p">([</span><span class="n">Decimal</span><span class="p">(</span><span class="s1">'0.1'</span><span class="p">)]</span><span class="o">*</span><span class="mi">10</span><span class="p">)</span> <span class="o">==</span> <span class="n">Decimal</span><span class="p">(</span><span class="s1">'1.0'</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">>>> </span><span class="nb">sum</span><span class="p">([</span><span class="mf">0.1</span><span class="p">]</span><span class="o">*</span><span class="mi">10</span><span class="p">)</span> <span class="o">==</span> <span class="mf">1.0</span>
<span class="go">False</span>
</pre></div>
</div>
<p><a class="reference external" href="https://docs.python.org/3/library/decimal.html#module-decimal">decimal</a> 提供了必须的高精度算法:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">getcontext</span><span class="p">()</span><span class="o">.</span><span class="n">prec</span> <span class="o">=</span> <span class="mi">36</span>
<span class="gp">>>> </span><span class="n">Decimal</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">Decimal</span><span class="p">(</span><span class="mi">7</span><span class="p">)</span>
<span class="go">Decimal('0.142857142857142857142857142857142857')</span>
</pre></div>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="venv.html" class="btn btn-neutral float-right" title="12. 虚拟环境和包">Next <span class="fa fa-arrow-circle-right"></span></a>
<a href="stdlib.html" class="btn btn-neutral" title="10. Python 标准库概览"><span class="fa fa-arrow-circle-left"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
© Copyright 2013, D.D.
</p>
</div>
Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'./',
VERSION:'3.5.2',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.StickyNav.enable();
});
</script>
</body>
</html>