├── .gitignore
├── LICENSE.md
├── README.md
├── SUMMARY.md
├── ThinkPython-0.5.md
├── ThinkPython-0.md
├── ThinkPython-1.md
├── ThinkPython-10.md
├── ThinkPython-11.md
├── ThinkPython-12.md
├── ThinkPython-13.md
├── ThinkPython-14.md
├── ThinkPython-15.md
├── ThinkPython-16.md
├── ThinkPython-17.md
├── ThinkPython-18.md
├── ThinkPython-19.md
├── ThinkPython-2.md
├── ThinkPython-3.md
├── ThinkPython-4.md
├── ThinkPython-5.md
├── ThinkPython-6.md
├── ThinkPython-7.md
├── ThinkPython-8.md
├── ThinkPython-9.md
├── cover.jpg
├── images
├── figure10.1.jpg
├── figure10.2.jpg
├── figure10.3.jpg
├── figure10.4.jpg
├── figure10.5.jpg
├── figure11.1.jpg
├── figure11.2.jpg
├── figure12.1.jpg
├── figure12.2.jpg
├── figure15.1.jpg
├── figure15.2.jpg
├── figure15.3.jpg
├── figure16.1.jpg
├── figure18.1.jpg
├── figure18.2.jpg
├── figure2.1.jpg
├── figure3.1.jpg
├── figure4.1-4.2.jpg
├── figure5.1.jpg
├── figure5.2.jpg
├── figure6.1.jpg
├── figure7.1.jpg
├── figure8.1.jpg
└── figure8.2.jpg
└── intro.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Node rules:
2 | ## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
3 | .grunt
4 |
5 | ## Dependency directory
6 | ## Commenting this out is preferred by some people, see
7 | ## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git
8 | node_modules
9 |
10 | # Book build output
11 | _book
12 |
13 | # eBook build output
14 | *.epub
15 | *.mobi
16 | *.pdf
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | CC0 1.0 Universal
2 |
3 | Statement of Purpose
4 |
5 | The laws of most jurisdictions throughout the world automatically confer
6 | exclusive Copyright and Related Rights (defined below) upon the creator and
7 | subsequent owner(s) (each and all, an "owner") of an original work of
8 | authorship and/or a database (each, a "Work").
9 |
10 | Certain owners wish to permanently relinquish those rights to a Work for the
11 | purpose of contributing to a commons of creative, cultural and scientific
12 | works ("Commons") that the public can reliably and without fear of later
13 | claims of infringement build upon, modify, incorporate in other works, reuse
14 | and redistribute as freely as possible in any form whatsoever and for any
15 | purposes, including without limitation commercial purposes. These owners may
16 | contribute to the Commons to promote the ideal of a free culture and the
17 | further production of creative, cultural and scientific works, or to gain
18 | reputation or greater distribution for their Work in part through the use and
19 | efforts of others.
20 |
21 | For these and/or other purposes and motivations, and without any expectation
22 | of additional consideration or compensation, the person associating CC0 with a
23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
25 | and publicly distribute the Work under its terms, with knowledge of his or her
26 | Copyright and Related Rights in the Work and the meaning and intended legal
27 | effect of CC0 on those rights.
28 |
29 | 1. Copyright and Related Rights. A Work made available under CC0 may be
30 | protected by copyright and related or neighboring rights ("Copyright and
31 | Related Rights"). Copyright and Related Rights include, but are not limited
32 | to, the following:
33 |
34 | i. the right to reproduce, adapt, distribute, perform, display, communicate,
35 | and translate a Work;
36 |
37 | ii. moral rights retained by the original author(s) and/or performer(s);
38 |
39 | iii. publicity and privacy rights pertaining to a person's image or likeness
40 | depicted in a Work;
41 |
42 | iv. rights protecting against unfair competition in regards to a Work,
43 | subject to the limitations in paragraph 4(a), below;
44 |
45 | v. rights protecting the extraction, dissemination, use and reuse of data in
46 | a Work;
47 |
48 | vi. database rights (such as those arising under Directive 96/9/EC of the
49 | European Parliament and of the Council of 11 March 1996 on the legal
50 | protection of databases, and under any national implementation thereof,
51 | including any amended or successor version of such directive); and
52 |
53 | vii. other similar, equivalent or corresponding rights throughout the world
54 | based on applicable law or treaty, and any national implementations thereof.
55 |
56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of,
57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
59 | and Related Rights and associated claims and causes of action, whether now
60 | known or unknown (including existing as well as future claims and causes of
61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum
62 | duration provided by applicable law or treaty (including future time
63 | extensions), (iii) in any current or future medium and for any number of
64 | copies, and (iv) for any purpose whatsoever, including without limitation
65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
66 | the Waiver for the benefit of each member of the public at large and to the
67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver
68 | shall not be subject to revocation, rescission, cancellation, termination, or
69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work
70 | by the public as contemplated by Affirmer's express Statement of Purpose.
71 |
72 | 3. Public License Fallback. Should any part of the Waiver for any reason be
73 | judged legally invalid or ineffective under applicable law, then the Waiver
74 | shall be preserved to the maximum extent permitted taking into account
75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
76 | is so judged Affirmer hereby grants to each affected person a royalty-free,
77 | non transferable, non sublicensable, non exclusive, irrevocable and
78 | unconditional license to exercise Affirmer's Copyright and Related Rights in
79 | the Work (i) in all territories worldwide, (ii) for the maximum duration
80 | provided by applicable law or treaty (including future time extensions), (iii)
81 | in any current or future medium and for any number of copies, and (iv) for any
82 | purpose whatsoever, including without limitation commercial, advertising or
83 | promotional purposes (the "License"). The License shall be deemed effective as
84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the
85 | License for any reason be judged legally invalid or ineffective under
86 | applicable law, such partial invalidity or ineffectiveness shall not
87 | invalidate the remainder of the License, and in such case Affirmer hereby
88 | affirms that he or she will not (i) exercise any of his or her remaining
89 | Copyright and Related Rights in the Work or (ii) assert any associated claims
90 | and causes of action with respect to the Work, in either case contrary to
91 | Affirmer's express Statement of Purpose.
92 |
93 | 4. Limitations and Disclaimers.
94 |
95 | a. No trademark or patent rights held by Affirmer are waived, abandoned,
96 | surrendered, licensed or otherwise affected by this document.
97 |
98 | b. Affirmer offers the Work as-is and makes no representations or warranties
99 | of any kind concerning the Work, express, implied, statutory or otherwise,
100 | including without limitation warranties of title, merchantability, fitness
101 | for a particular purpose, non infringement, or the absence of latent or
102 | other defects, accuracy, or the present or absence of errors, whether or not
103 | discoverable, all to the greatest extent permissible under applicable law.
104 |
105 | c. Affirmer disclaims responsibility for clearing rights of other persons
106 | that may apply to the Work or any use thereof, including without limitation
107 | any person's Copyright and Related Rights in the Work. Further, Affirmer
108 | disclaims responsibility for obtaining any necessary consents, permissions
109 | or other rights required for any use of the Work.
110 |
111 | d. Affirmer understands and acknowledges that Creative Commons is not a
112 | party to this document and has no duty or obligation with respect to this
113 | CC0 or use of the Work.
114 |
115 | For more information, please see
116 |
117 |
118 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ThinkPython-en-cn
2 |
3 | # ThinkPython 中英双语
4 |
5 | #
6 |
7 | 此处为 markdown 的文本文件。与我[博客](http://blog.cycleuser.org)的内容同步.
8 |
9 | 此处仅保留双语版本,纯中文版迁移到[ThinkPython-CN](https://github.com/cycleuser/ThinkPython-CN)
10 |
11 | 可以到:[这里在线阅读和下载电子文档](https://www.gitbook.com/book/cycleuser/think-python/details)。
12 |
13 | 有任何问题请在 issue 中留言,或者可以移步访问[我的博客]([http://blog.cycleuser.org)或者
14 | [我的专栏](https://zhuanlan.zhihu.com/python-kivy)。
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [ReadMe](README.md)
4 | * [Intro 简介](ThinkPython-0.md)
5 | * [Preface 前言](ThinkPython-0.5.md)
6 | * [Chapter 1 The way of the program 编程之路](ThinkPython-1.md)
7 | * [Chapter 2 Variables, expressions and statements 变量,表达式,语句](ThinkPython-2.md)
8 | * [Chapter 3 Functions 函数](ThinkPython-3.md)
9 | * [Chapter 4 Case study: interface design 案例学习:交互设计](ThinkPython-4.md)
10 | * [Chapter 5 Conditionals and recursion 条件循环](ThinkPython-5.md)
11 | * [Chapter 6 Fruitful functions 有返回值的函数](ThinkPython-6.md)
12 | * [Chapter 7 Iteration 迭代](ThinkPython-7.md)
13 | * [Chapter 8 Strings 字符串](ThinkPython-8.md)
14 | * [Chapter 9 Case study: word play 案例学习:单词游戏](ThinkPython-9.md)
15 | * [Chapter 10 Lists 列表](ThinkPython-10.md)
16 | * [Chapter 11 Dictionaries 字典](ThinkPython-11.md)
17 | * [Chapter 12 Tuples 元组](ThinkPython-12.md)
18 | * [Chapter 13 Case study: data structure selection 案例学习:数据结构的选择](ThinkPython-13.md)
19 | * [Chapter 14 Files 文件](ThinkPython-14.md)
20 | * [Chapter 15 Classes and objects 类和对象](ThinkPython-15.md)
21 | * [Chapter 16 Classes and functions 类和函数](ThinkPython-16.md)
22 | * [Chapter 17 Classes and methods 类和方法](ThinkPython-17.md)
23 | * [Chapter 18 Inheritance 继承](ThinkPython-18.md)
24 | * [Chapter 19 The Goodies 额外补充](ThinkPython-19.md)
25 |
26 |
--------------------------------------------------------------------------------
/ThinkPython-0.5.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 0.5 Preface 前言
2 | Date: 2015-10-21
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 0 Preface 前言
7 | ##The strange history of this book
8 | >本书的奇幻历史
9 |
10 | In January 1999 I was preparing to teach an introductory programming class in Java. I had taught it three times and I was getting frustrated. The failure rate in the class was too high and, even for students who succeeded, the overall level of achievement was too low.
11 | >在1999年1月的时候呢,我正准备教一门Java的入门编程课。
12 | 我当时已经教过三次了,受挫感很强。班上挂科率特别高,而且即使那些没挂科的学生编程的整体水平也特别低。
13 |
14 | One of the problems I saw was the books. They were too big, with too much unnecessary detail about Java, and not enough high-level guidance about how to program. And they all suffered from the trap door effect: they would start out easy, proceed gradually, and then somewhere around Chapter 5 the bottom would fall out. The students would get too much new material, too fast, and I would spend the rest of the semester picking up the pieces.
15 | >当时有很多问题,我首先发现的就是教材。那些教材都特别大部头,有很多关于Java的细节,特别琐碎又并不重要,而且也没有足够的关于如何编程的高层次指导(译者注:就是缺乏战略性指导,没有告诉学生编程的心法)。这些教材总有一些『陷阱门效应』:开头他们都却是挺简单,然后逐步提升,接着突然在某个地方,比如第五章,出现很坑很复杂的陷阱。学生们要突然一下子应对太多新东西,甚至措手不及,而我作为教师就得花费整个后半个学期来一点点给学生们补上。
16 |
17 | Two weeks before the first day of classes, I decided to write my own book. My goals were:
18 |
19 | * Keep it short. It is better for students to read 10 pages than not read 50 pages.
20 | * Be careful with vocabulary. I tried to minimize jargon and define each term at first use.
21 | * Build gradually. To avoid trap doors, I took the most difficult topics and split them into a series of small steps.
22 | * Focus on programming, not the programming language. I included the minimum useful subset of Java and left out the rest.
23 |
24 | I needed a title, so on a whim I chose How to Think Like a Computer Scientist.
25 |
26 | 开课的两周之前,我最终决定要写个自己的教科书。目标如下:
27 |
28 | * 简短。让学生读10页就够比让他们读50页效果好得多。
29 | * 降低词汇难度。我尽量把术语用量降到最低,并且在首次使用的时候对每一个都进行定义。
30 | * 循序渐进。为了避免『陷阱门效应』,我专门把这些最为复杂的部分抽离成一个个专题,并且都切分成小规模的部分,一步步来进行。
31 | * 专注于编程,而不是编程语言。我只保留了关于Java的最小规模内容,没有涉及更多的细节。
32 | 我还需要个标题,就突发奇想,选了个标题叫做『如何像计算机科学家一样思考』。
33 |
34 | My first version was rough, but it worked. Students did the reading, and they understood enough that I could spend class time on the hard topics, the interesting topics and (most important) letting the students practice.
35 | >我的第一版教材很粗糙,但挺管用。学生真能看进去,并且理解了我在课上所讲的那些难点和有趣的专题,最重要的是,他们能够据此来实践。
36 |
37 | I released the book under the GNU Free Documentation License, which allows users to copy, modify, and distribute the book.
38 | >之后我就以GNU自由文档协议来发布了这本书,这一协议允许所有人去复制、修改以及分发这本书。
39 |
40 | What happened next is the cool part. Jeff Elkner, a high school teacher in Virginia, adopted my book and translated it into Python. He sent me a copy of his translation, and I had the unusual experience of learning Python by reading my own book. As Green Tea Press, I published the first Python version in 2001.
41 | >接下来的事情很有趣了。Jeff Elkner,维吉尼亚的一位高中教师,他很欣赏我这本书,把这本书从Java翻译成了Python的版本。他发给我一份『译稿』,然后我开启了阅读『自己的书』来学习Python的奇妙经历。于是在2001年,我通过Green Tea Press出版了本书的第一个Python版本。
42 |
43 | In 2003 I started teaching at Olin College and I got to teach Python for the first time. The contrast with Java was striking. Students struggled less, learned more, worked on more interesting projects, and generally had a lot more fun.
44 | >在2003年,我开始在奥林商学院教学,并且第一次开始教Python了。这和Java的对比很鲜明。学生们省力多了,学得也更多了,在有趣的项目上也更努力,整体上都觉得这一学习过程很有乐趣。
45 |
46 | Since then I’ve continued to develop the book, correcting errors, improving some of the examples and adding material, especially exercises.
47 | >从那以后,我就继续维护这本书,修正错误,改进样例、附加资料以及练习题。
48 |
49 | The result is this book, now with the less grandiose title Think Python. Some of the changes are:
50 |
51 | * I added a section about debugging at the end of each chapter. These sections present general techniques for finding and avoiding bugs, and warnings about Python pitfalls.
52 | * I added more exercises, ranging from short tests of understanding to a few substantial projects. Most exercises include a link to my solution.
53 | * I added a series of case studies—longer examples with exercises, solutions, and discussion.
54 | * I expanded the discussion of program development plans and basic design patterns.
55 | * I added appendices about debugging and analysis of algorithms.
56 |
57 | >结果就产生了现在这本书,现在标题简化了很多——Think Python。主要的改变如下:
58 |
59 | >* 在每一章的末尾,我加了关于debug的部分。这些内容提供了关于debug的一些整体策略,比如如何找到和避免bug,还有就是关于Python一些陷阱进行了提醒。
60 | >* 我加了更多的练习,从简单的理解方面的测试,到一些比较充足的项目。大多数练习都有解决方案的样本链接。
61 | >* 我还添加了一些案例研究,包含练习、解决方案和讨论的更大规模的样例。
62 | >* 此外我还扩展了关于程序开发规划和基本设计模式的讨论。
63 | >* 关于debug和算法分析,还额外加了一些附录。
64 |
65 | The second edition of Think Python has these new features:
66 |
67 | * The book and all supporting code have been updated to Python 3.
68 | * I added a few sections, and more details on the web, to help beginners get started running Python in a browser, so you don’t have to deal with installing Python until you want to.
69 | * For Chapter 4.1 I switched from my own turtle graphics package, called Swampy, to a more standard Python module, turtle, which is easier to install and more powerful.
70 | * I added a new chapter called “The Goodies”, which introduces some additional Python features that are not strictly necessary, but sometimes handy.
71 |
72 | >这本Think Python 的第二版有如下的新内容:
73 |
74 | >* 本书内的所有参考代码都升级到Python3了。
75 | >* 我增加了一部分内容,以及一些关于web方面的细节,这是为了帮助初学者能够在浏览器中开始尝试Python,这样即便你不想安装Python也没问题了。
76 | >* 在第四章的第一节,我把我自己的一个原来叫做Swampy的小乌龟图形包转换撑了一个更标准的Python模块,名字叫做turtle,更好安装,功能也比之前强大了。
77 | >* 我还添加了新的一章,叫做『彩蛋』,介绍了一些Python的额外功能,严格来说,这些功能并不算必备的,但有时候蛮好用的。
78 |
79 | I hope you enjoy working with this book, and that it helps you learn to program and think like a computer scientist, at least a little bit.
80 | >我希望大家能享受学习这本书的过程,也希望这本书能帮助大家学习编程,并且让大家学会像计算机科学家一样思考,哪怕有一点点也好。
81 |
82 | Allen B. Downey
83 | >艾伦 唐尼
84 |
85 | Olin College
86 | >奥林商学院
87 |
88 | ##Acknowledgments
89 | >##致谢
90 |
91 | Many thanks to Jeff Elkner, who translated my Java book into Python, which got this project started and introduced me to what has turned out to be my favorite language.
92 | >非常感谢Jeff Elkner,是他把我的Java教材翻译成了Python,才引起了这一项目的开始,并且也把Python语言介绍给我,它已经是我最喜欢的编程语言了。
93 |
94 | Thanks also to Chris Meyers, who contributed several sections to How to Think Like a Computer Scientist.
95 | >也要感谢Chris Meyers,他对『如何像计算机科学家一样思考』的一些章节有贡献。
96 |
97 | Thanks to the Free Software Foundation for developing the GNU Free Documentation License, which helped make my collaboration with Jeff and Chris possible, and Creative Commons for the license I am using now.
98 | >感谢自由软件基金会,是他们提出了GNU自由文档协议,在这一协议的帮助下,我和Jeff以及Chris的合作成为了可能,当然也要感谢我现在使用的知识共享协议。
99 |
100 | Thanks to the editors at Lulu who worked on How to Think Like a Computer Scientist.
101 | >感谢Lulu的编辑们,他们出版了『如何像计算机科学家一样思考』。
102 |
103 | Thanks to the editors at O’Reilly Media who worked on Think Python.
104 | >感谢O’Reilly公司的编辑们,他们出版了这本『Think Python』。
105 |
106 | Thanks to all the students who worked with earlier versions of this book and all the contributors (listed below) who sent in corrections and suggestions.
107 | >最后还要感谢所有曾对本书早期版本做出过贡献的同学们,以及其他参与改错和提出建议的朋友们(列表如下)。
108 | ###Contributor List
109 | >###贡献列表
110 |
111 | More than 100 sharp-eyed and thoughtful readers have sent in suggestions and corrections over the past few years. Their contributions, and enthusiasm for this project, have been a huge help.
112 | >百名以上目光敏锐又思维迅捷的读者都在过去的这些年里发来了各种建议或是发现了各种错误。他们贡献和热情都是对本项目的巨大帮助。
113 |
114 | If you have a suggestion or correction, please send email tofeedback@thinkpython2.com. If I make a change based on your feedback, I will add you to the contributor list (unless you ask to be omitted).
115 | >如果大家有任何意见建议,请发邮件到feedback@thinkpython2.com联系我们。如果基于反馈做出了修改,我会将你添加到贡献列表(当然你不想被添加也可以的)。
116 |
117 | If you include at least part of the sentence the error appears in, that makes it easy for me to search. Page and section numbers are fine, too, but not quite as easy to work with. Thanks!
118 | >希望你能至少把出错句子的一部分提供出来,这都让我更容易去搜索。页码和章节编号也可以,但不太容易找。多谢了!
119 | (译者注:以下贡献列表不翻译了)
120 |
121 | * Lloyd Hugh Allen sent in a correction to Section 8.4.
122 | * Yvon Boulianne sent in a correction of a semantic error in Chapter 5.
123 | * Fred Bremmer submitted a correction in Section 2.1.
124 | * Jonah Cohen wrote the Perl scripts to convert the LaTeX source for this book into beautiful HTML.
125 | * Michael Conlon sent in a grammar correction in Chapter 2 and an improvement in style in Chapter 1, and he initiated discussion on the technical aspects of interpreters.
126 | * Benoit Girard sent in a correction to a humorous mistake in Section 5.6.
127 | * Courtney Gleason and Katherine Smith wrote horsebet.py, which was used as a case study in an earlier version of the book. Their program can now be found on the website.
128 | * Lee Harr submitted more corrections than we have room to list here, and indeed he should be listed as one of the principal editors of the text.
129 | * James Kaylin is a student using the text. He has submitted numerous corrections.
130 | * David Kershaw fixed the broken catTwice function in Section 3.10.
131 | * Eddie Lam has sent in numerous corrections to Chapters 1, 2, and 3. He also fixed the Makefile so that it creates an index the first time it is run and helped us set up a versioning scheme.
132 | * Man-Yong Lee sent in a correction to the example code in Section 2.4.
133 | * David Mayo pointed out that the word “unconsciously" in Chapter 1 needed to be changed to “subconsciously".
134 | * Chris McAloon sent in several corrections to Sections 3.9 and 3.10.
135 | * Matthew J. Moelter has been a long-time contributor who sent in numerous corrections and suggestions to the book.
136 | * Simon Dicon Montford reported a missing function definition and several typos in Chapter 3. He also found errors in the increment function in Chapter 13.
137 | * John Ouzts corrected the definition of “return value" in Chapter 3.
138 | * Kevin Parks sent in valuable comments and suggestions as to how to improve the distribution of the book.
139 | * David Pool sent in a typo in the glossary of Chapter 1, as well as kind words of encouragement.
140 | * Michael Schmitt sent in a correction to the chapter on files and exceptions.
141 | * Robin Shaw pointed out an error in Section 13.1, where the printTime function was used in an example without being defined.
142 | * Paul Sleigh found an error in Chapter 7 and a bug in Jonah Cohen’s Perl script that generates HTML from LaTeX.
143 | * Craig T. Snydal is testing the text in a course at Drew University. He has contributed several valuable suggestions and corrections.
144 | * Ian Thomas and his students are using the text in a programming course. They are the first ones to test the chapters in the latter half of the book, and they have made numerous corrections and suggestions.
145 | * Keith Verheyden sent in a correction in Chapter 3.
146 | * Peter Winstanley let us know about a longstanding error in our Latin in Chapter 3.
147 | * Chris Wrobel made corrections to the code in the chapter on file I/O and exceptions.
148 | * Moshe Zadka has made invaluable contributions to this project. In addition to writing the first draft of the chapter on Dictionaries, he provided continual guidance in the early stages of the book.
149 | * Christoph Zwerschke sent several corrections and pedagogic suggestions, and explained the difference between gleich and selbe.
150 | * James Mayer sent us a whole slew of spelling and typographical errors, including two in the contributor list.
151 | * Hayden McAfee caught a potentially confusing inconsistency between two examples.
152 | * Angel Arnal is part of an international team of translators working on the Spanish version of the text. He has also found several errors in the English version.
153 | * Tauhidul Hoque and Lex Berezhny created the illustrations in Chapter 1 and improved many of the other illustrations.
154 | * Dr. Michele Alzetta caught an error in Chapter 8 and sent some interesting pedagogic comments and suggestions about Fibonacci and Old Maid.
155 | * Andy Mitchell caught a typo in Chapter 1 and a broken example in Chapter 2.
156 | * Kalin Harvey suggested a clarification in Chapter 7 and caught some typos.
157 | * Christopher P. Smith caught several typos and helped us update the book for Python 2.2.
158 | * David Hutchins caught a typo in the Foreword.
159 | * Gregor Lingl is teaching Python at a high school in Vienna, Austria. He is working on a German translation of the book, and he caught a couple of bad errors in Chapter 5.
160 | * Julie Peters caught a typo in the Preface.
161 | * Florin Oprina sent in an improvement in makeTime, a correction inprintTime, and a nice typo.
162 | * D. J. Webre suggested a clarification in Chapter 3.
163 | * Ken found a fistful of errors in Chapters 8, 9 and 11.
164 | * Ivo Wever caught a typo in Chapter 5 and suggested a clarification in Chapter 3.
165 | * Curtis Yanko suggested a clarification in Chapter 2.
166 | * Ben Logan sent in a number of typos and problems with translating the book into HTML.
167 | * Jason Armstrong saw the missing word in Chapter 2.
168 | * Louis Cordier noticed a spot in Chapter 16 where the code didn’t match the text.
169 | * Brian Cain suggested several clarifications in Chapters 2 and 3.
170 | * Rob Black sent in a passel of corrections, including some changes for Python 2.2.
171 | * Jean-Philippe Rey at Ecole Centrale Paris sent a number of patches, including some updates for Python 2.2 and other thoughtful improvements.
172 | * Jason Mader at George Washington University made a number of useful suggestions and corrections.
173 | * Jan Gundtofte-Bruun reminded us that “a error” is an error.
174 | * Abel David and Alexis Dinno reminded us that the plural of “matrix” is “matrices”, not “matrixes”. This error was in the book for years, but two readers with the same initials reported it on the same day. Weird.
175 | * Charles Thayer encouraged us to get rid of the semi-colons we had put at the ends of some statements and to clean up our use of “argument” and “parameter”.
176 | * Roger Sperberg pointed out a twisted piece of logic in Chapter 3.
177 | * Sam Bull pointed out a confusing paragraph in Chapter 2.
178 | * Andrew Cheung pointed out two instances of “use before def”.
179 | * C. Corey Capel spotted the missing word in the Third Theorem of Debugging and a typo in Chapter 4.
180 | * Alessandra helped clear up some Turtle confusion.
181 | * Wim Champagne found a brain-o in a dictionary example.
182 | * Douglas Wright pointed out a problem with floor division in arc.
183 | * Jared Spindor found some jetsam at the end of a sentence.
184 | * Lin Peiheng sent a number of very helpful suggestions.
185 | * Ray Hagtvedt sent in two errors and a not-quite-error.
186 | * Torsten Hübsch pointed out an inconsistency in Swampy.
187 | * Inga Petuhhov corrected an example in Chapter 14.
188 | * Arne Babenhauserheide sent several helpful corrections.
189 | * Mark E. Casida is is good at spotting repeated words.
190 | * Scott Tyler filled in a that was missing. And then sent in a heap of corrections.
191 | * Gordon Shephard sent in several corrections, all in separate emails.
192 | * Andrew Turner spotted an error in Chapter 8.
193 | * Adam Hobart fixed a problem with floor division in arc.
194 | * Daryl Hammond and Sarah Zimmerman pointed out that I served upmath.pi too early. And Zim spotted a typo.
195 | * George Sass found a bug in a Debugging section.
196 | * Brian Bingham suggested Exercise 5.
197 | * Leah Engelbert-Fenton pointed out that I used tuple as a variable name, contrary to my own advice. And then found a bunch of typos and a “use before def”.
198 | * Joe Funke spotted a typo.
199 | * Chao-chao Chen found an inconsistency in the Fibonacci example.
200 | * Jeff Paine knows the difference between space and spam.
201 | * Lubos Pintes sent in a typo.
202 | * Gregg Lind and Abigail Heithoff suggested Exercise 3.
203 | * Max Hailperin has sent in a number of corrections and suggestions. Max is one of the authors of the extraordinary Concrete Abstractions, which you might want to read when you are done with this book.
204 | * Chotipat Pornavalai found an error in an error message.
205 | * Stanislaw Antol sent a list of very helpful suggestions.
206 | * Eric Pashman sent a number of corrections for Chapters 4–11.
207 | * Miguel Azevedo found some typos.
208 | * Jianhua Liu sent in a long list of corrections.
209 | * Nick King found a missing word.
210 | * Martin Zuther sent a long list of suggestions.
211 | * Adam Zimmerman found an inconsistency in my instance of an “instance” and several other errors.
212 | * Ratnakar Tiwari suggested a footnote explaining degenerate triangles.
213 | * Anurag Goel suggested another solution for is_abecedarian and sent some additional corrections. And he knows how to spell Jane Austen.
214 | * Kelli Kratzer spotted one of the typos.
215 | * Mark Griffiths pointed out a confusing example in Chapter 3.
216 | * Roydan Ongie found an error in my Newton’s method.
217 | * Patryk Wolowiec helped me with a problem in the HTML version.
218 | * Mark Chonofsky told me about a new keyword in Python 3.
219 | * Russell Coleman helped me with my geometry.
220 | * Wei Huang spotted several typographical errors.
221 | * Karen Barber spotted the the oldest typo in the book.
222 | * Nam Nguyen found a typo and pointed out that I used the Decorator pattern but didn’t mention it by name.
223 | * Stéphane Morin sent in several corrections and suggestions.
224 | * Paul Stoop corrected a typo in uses_only.
225 | * Eric Bronner pointed out a confusion in the discussion of the order of operations.
226 | * Alexandros Gezerlis set a new standard for the number and quality of suggestions he submitted. We are deeply grateful!
227 | * Gray Thomas knows his right from his left.
228 | * Giovanni Escobar Sosa sent a long list of corrections and suggestions.
229 | * Alix Etienne fixed one of the URLs.
230 | * Kuang He found a typo.
231 | * Daniel Neilson corrected an error about the order of operations.
232 | * Will McGinnis pointed out that polyline was defined differently in two places.
233 | * Swarup Sahoo spotted a missing semi-colon.
234 | * Frank Hecker pointed out an exercise that was under-specified, and some broken links.
235 | * Animesh B helped me clean up a confusing example.
236 | * Martin Caspersen found two round-off errors.
237 | * Gregor Ulm sent several corrections and suggestions.
238 | * Dimitrios Tsirigkas suggested I clarify an exercise.
239 | * Carlos Tafur sent a page of corrections and suggestions.
240 | * Martin Nordsletten found a bug in an exercise solution.
241 | * Lars O.D. Christensen found a broken reference.
242 | * Victor Simeone found a typo.
243 | * Sven Hoexter pointed out that a variable named input shadows a build-in function.
244 | * Viet Le found a typo.
245 | * Stephen Gregory pointed out the problem with cmp in Python 3.
246 | * Matthew Shultz let me know about a broken link.
247 | * Lokesh Kumar Makani let me know about some broken links and some changes in error messages.
248 | * Ishwar Bhat corrected my statement of Fermat’s last theorem.
249 | * Brian McGhie suggested a clarification.
250 | * Andrea Zanella translated the book into Italian, and sent a number of corrections along the way.
251 | * Many, many thanks to Melissa Lewis and Luciano Ramalho for excellent comments and suggestions on the second edition.
252 | * Thanks to Harry Percival from PythonAnywhere for his help getting people started running Python in a browser.
253 |
254 |
255 |
256 |
257 |
--------------------------------------------------------------------------------
/ThinkPython-0.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 0 简介
2 | Date: 2015-10-20
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Think Python
7 | >2nd Edition
8 | >by Allen B. Downey
9 | >翻译 大胖哥
10 |
11 | 有任何问题请在 issue 中留言,或者可以移步访问[我的博客](http://blog.cycleuser.org)或者[我的专栏](https://zhuanlan.zhihu.com/python-kivy)。
12 |
13 | This is a very classical book for newbies of programing. There are some versions of translation. But I still think that we can do it by ourselves.
14 | >这是一本很经典的编程入门书籍。网上有过一些翻译,不过我觉得咱们还是自己来一下比较好!
15 |
16 | This is the second edition of Think Python. It uses Python 3, with notes on differences in Python 2. If you are using Python 2, you might want to use [the first edition](http://www.greenteapress.com/thinkpython/index.html).
17 | >这是Think Python这本书的第二版,本次使用的是Python3,与Python2有很多不同,这些不同之处会有标注。如果你用Python2的货,还是建议你去阅读[上一个版本](http://www.greenteapress.com/thinkpython/index.html)。
18 |
19 | Buy the first edition at [Amazon.com ](http://amzn.to/Owtmjy)
20 | >到[亚马逊](http://amzn.to/Owtmjy)购买本书
21 |
22 | Download Think Python 2e in [PDF](http://www.greenteapress.com/thinkpython2/thinkpython2.pdf).
23 | >下载 Think Python 2e [PDF格式的电子版.](http://www.greenteapress.com/thinkpython2/thinkpython2.pdf)
24 |
25 | Read Think Python 2e in [HTML](http://www.greenteapress.com/thinkpython2/html/index.html).
26 | >在线阅读 Think Python 2e [HTML网页版本](http://www.greenteapress.com/thinkpython2/html/index.html)(推荐这个,都是文字格式,更方便).
27 |
28 | Example programs and solutions to some problems are [here](http://www.greenteapress.com/thinkpython2/code) (links to specific examples are in the book).
29 | >样例代码以及其他问题的解决可以到[这里](http://www.greenteapress.com/thinkpython2/code)找(具体样例的链接在书中就有)。
30 |
31 | ##Description 说明
32 |
33 | Think Python is an introduction to Python programming for beginners.
34 | >Think Python 这本书是面向初学者介绍Python编程。
35 |
36 | It starts with basic concepts of programming, and is carefully designed to define all terms when they are first used and to develop each new concept in a logical progression.
37 | >首先介绍的是一些编程的基本内容,给出概念和解释,然后循序渐进地深入讲解每个概念。
38 |
39 | Larger pieces, like recursion and object-oriented programming are divided into a sequence of smaller steps and introduced over the course of several chapters.
40 | >复杂的部分,比如递归以及面向对象编程,这些都分成一个个小块,以多个章节的方式来逐步介绍。
41 |
42 |
43 | What's new in the second edition?
44 | >第二版有啥新东西呢?
45 |
46 | * We've upgraded to Python 3: All examples in the book are now Python 3, and the supporting code has been updated to run in both Python 2 and 3.
47 | >开始用Python3了:书里面所有样例都用Python3来实现,参考代码也都做了升级,用Python2或者3都能运行。
48 |
49 | * We've removed the roadblocks: Based on reader feedback, we know where people had problems, so we've fixed or removed the pain points.
50 | >去掉了一些比较难的内容:基于读者反馈,我们认识到大家存在某些困难,所以就调整或者去掉了一些难点。
51 |
52 | * Python in the browser: For beginners, one of the challenges of getting started is installing Python. For readers who don't want to install Python right away, we provide instructions for running Python in a browser using PythonAnywhere, a free online programming environment.
53 | >浏览器内能Python编程了:初学者遇到的第一个困难就是安装Python。另外有的读者可能不想去直接就安装Python,我们就提供了一个用浏览器来运行Python的简介:使用PythonAnywhere,一个免费的在线Python编程环境。(译者注:中国用户以考虑试试fenby.com,也有类似的实现,还有视频的介绍。)
54 |
55 | * More Python goodies: We've added a chapter to cover some powerful Python features that didn't make it into the first edition, including list comprehensions and additional data structures.
56 | >更多Python彩蛋:单独加了一章,来介绍一些第一版中没有提及的Python功能,比如列表解析和附加的数据结构。
57 |
58 | Think Python 2e is a Free Book.
59 | >这本书是一本自-和谐-由的书。
60 |
61 | It is available under the [Creative Commons Attribution-NonCommercial 3.0 Unported License](http://creativecommons.org/licenses/by-nc/3.0/), which means that you are free to copy, distribute, and modify it, as long as you attribute the work and don't use it for commercial purposes.
62 | >本书遵循[创作共用署名-非商业性使用-第三版协议](http://creativecommons.org/licenses/by-nc/3.0/),这意味着你可以自-和谐-由地复制、分发和修改他,只要你有所贡献,并且不用于商业目的,就可以。
63 |
64 | If you have comments, corrections or suggestions, please send me email at feedback{at}thinkpython{dot}com.
65 | >如果你有一些评论、修正或者建议,可以发邮件给feedback@thinkpython.com
66 |
67 | Other Free Books by Allen Downey are available from [Green Tea Press](http://greenteapress.com/).
68 | >其他由 Allen Downey 编写的自-和谐-由书籍都可以在[Green Tea Press](http://greenteapress.com/)找到.
69 |
70 |
71 | ##Download 下载
72 |
73 | * Precompiled copies of the book are available in [PDF](http://www.greenteapress.com/thinkpython2/thinkpython2.pdf).
74 | >编译好的PDF版本在这里下载:[PDF](http://www.greenteapress.com/thinkpython2/thinkpython2.pdf)。
75 |
76 | * The LaTeX source code is available from [this GitHub repository](https://github.com/AllenDowney/ThinkPython2).
77 | >LaTeX代码在GitHub这里可以下载:[this GitHub repository](https://github.com/AllenDowney/ThinkPython2).
78 | * Here is the HTML version, and here is the HTML code in a zip archive.
79 | >网页在线阅读 HTML version, 这些网页打包下载 HTML code ,这是一个zip格式的压缩包。
80 |
81 |
82 | ##Earlier Versions
83 | >早期版本
84 |
85 | The first edition is [here](http://www.greenteapress.com/thinkpython).
86 | >第一版在[这里](http://www.greenteapress.com/thinkpython)
87 |
88 | A previous edition of this book was published by Cambridge University press with the title Python for Software Design. This edition is available from Amazon.com.
89 | >本书的上一个版本是由剑桥大学出版社出版的,标题是 Python for Software Design. 可以到亚马逊去买到哈。
90 |
91 | The original Python version of the book was published by Green Tea Press with the title How to Think Like a Computer Scientist: Learning with Python. This edition is available from from Lulu.com.
92 | >本书的原始版本由Green Tea Press 出版,标题为 How to Think Like a Computer Scientist: Learning with Python. 这个版本可以从这个网站找到 Lulu.com.
93 |
94 |
95 | Other Free Books by Allen Downey are available from Green Tea Press.
96 | >其他由 Allen Downey 编写的自-和谐-由书籍都可以在Green Tea Press找到.
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/ThinkPython-1.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 1
2 | Date: 2015-10-22
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | # Chapter 1 The way of the program 编程之路
7 |
8 | The goal of this book is to teach you to think like a computer scientist. This way of thinking combines some of the best features of mathematics, engineering, and natural science. Like mathematicians, computer scientists use formal languages to denote ideas \(specifically computations\). Like engineers, they design things, assembling components into systems and evaluating tradeoffs among alternatives. Like scientists, they observe the behavior of complex systems, form hypotheses, and test predictions.
9 |
10 | > 本书的目的是叫你学会像计算机科学家一样来思考。这种思考方式汇聚了数学、工程和自然科学的精华。计算机科学家像数学家一样,使用规范的语言来阐述思想(尤其是一些计算);像工程师一样设计、组装系统,并且在多重选择中寻找最优解;像自然科学家一样观察复杂系统的行为模式,建立猜想,测试预估的结果。
11 |
12 | The single most important skill for a computer scientist is problem solving. Problem solving means the ability to formulate problems, think creatively about solutions, and express a solution clearly and accurately. As it turns out, the process of learning to program is an excellent opportunity to practice problem-solving skills. That’s why this chapter is called, “The way of the program”.
13 |
14 | > 计算机科学家唯一最重要的技能就是『解决问题』。解决问题意味着要有能力把问题进行方程化,创造性地考虑解决思路,并且清晰又精确地表达出解决方案。而学习编程的过程,正是一个培养这种解决问题能力的绝佳机会。本章的标题是『编程之路』,原因就在此。
15 |
16 | On one level, you will be learning to program, a useful skill by itself. On another level, you will use programming as a means to an end. As we go along, that end will become clearer.
17 |
18 | > 在一定层面上,大家将通过编程本身来学习编程这一重要的技巧。在另外一些层面上,大家也将把编程作为实现一种目的的途径。这一目的会随着我们逐渐学习而越发清楚。
19 | >
20 | > ## 1.1 What is a program? 程序是什么?
21 | >
22 | > A program is a sequence of instructions that specifies how to perform a computation. The computation might be something mathematical, such as solving a system of equations or finding the roots of a polynomial, but it can also be a symbolic computation, such as searching and replacing text in a document or something graphical, like processing an image or playing a video.
23 | > 程序是一个指令的序列,来告诉机器如何进行一组运算。这种运算也许是数学上的,比如求解一组等式或者求多项式的根;当然也可以是符号运算,比如在文档中搜索和替换文字,或者一些图形化过程,比如处理图像或者播放一段视频。
24 |
25 | The details look different in different languages, but a few basic instructions appear in just about every language:
26 |
27 | > 不同编程语言的具体细节看着很不一样,但几乎所有编程语言都会有一些基础指令:
28 |
29 | * input: Get data from the keyboard, a file, the network, or some other device.
30 |
31 | > * 输入系统:从键盘、文件、网络或者其他设备上获得数据。
32 |
33 | * output: Display data on the screen, save it in a file, send it over the network, etc.
34 |
35 | > * 输出系统:将数据在屏幕中显示,或者存到文件中、通过网络发送等等。
36 |
37 | * math: Perform basic mathematical operations like addition and multiplication.
38 |
39 | > * 数学运算:进行基本的数学操作,比如加法或者乘法。
40 |
41 | * conditional execution: Check for certain conditions and run the appropriate code.
42 |
43 | > * 条件判断:检查特定条件是否满足来运行相应的代码。
44 |
45 | * repetition: Perform some action repeatedly, usually with some variation.
46 |
47 | > * 重复判断:重复进行一些操作,通常会有些变化。
48 |
49 | Believe it or not, that’s pretty much all there is to it. Every program you’ve ever used, no matter how complicated, is made up of instructions that look pretty much like these. So you can think of programming as the process of breaking a large, complex task into smaller and smaller subtasks until the subtasks are simple enough to be performed with one of these basic instructions.
50 |
51 | > 大家可能不太相信,核心内容就这么多。你用过的所有程序,无论多么复杂,都是由一些这样的指令组合而成的。因此大家可以把编程的过程理解成一个把庞大复杂任务进行拆分来解决的过程,分解到适合使用上述的基本指令来解决为止。
52 |
53 | ## 1.2 Running Python 运行Python
54 |
55 | One of the challenges of getting started with Python is that you might have to install Python and related software on your computer. If you are familiar with your operating system, and especially if you are comfortable with the command-line interface, you will have no trouble installing Python. But for beginners, it can be painful to learn about system administration and programming at the same time.
56 |
57 | > 新手在刚接触Python的时候遇到的困难之一就是必须在电脑上安装Python和相关的一些软件。如果你熟悉操作系统,并且还很习惯用命令行界面,那安装Python对你来说就没啥问题了。但对初学者来说,要求他们既要了解系统管理又要学习编程,就可能有些困难了。
58 |
59 | To avoid that problem, I recommend that you start out running Python in a browser. Later, when you are comfortable with Python, I’ll make suggestions for installing Python on your computer.
60 |
61 | > 为了避免这种问题,我推荐大家可以在开始的时候用浏览器来体验Python。熟悉了之后,再安装Python到计算机上。
62 |
63 | There are a number of web pages you can use to run Python. If you already have a favorite, go ahead and use it. Otherwise I recommend PythonAnywhere. I provide detailed instructions for getting started at [http://tinyurl.com/thinkpython2e](http://tinyurl.com/thinkpython2e).
64 |
65 | > 有很多站点提供在线运行Python的功能。如果你已经用过并且有一定经验了,可以选择你喜欢的。我推荐大家可以试试PythonAnywhere,对此的使用介绍可以在下面的链接中找到 [http://tinyurl.com/thinkpython2e](http://tinyurl.com/thinkpython2e)。
66 |
67 | There are two versions of Python, called Python 2 and Python 3. They are very similar, so if you learn one, it is easy to switch to the other. In fact, there are only a few differences you will encounter as a beginner. This book is written for Python 3, but I include some notes about Python 2.
68 |
69 | > Python现在有两个主要的分之,即Python2和Python3。如果你学过其中的一个,你会发现他们还挺相似的,而且转换起来也不算难。实际上对于初学者来说,他们只有很细微的差别而已。这本书是用Python3写的,但也会对Python2进行注解。
70 |
71 | The Python interpreter is a program that reads and executes Python code. Depending on your environment, you might start the interpreter by clicking on an icon, or by typing python on a command line. When it starts, you should see output like this:
72 |
73 | > Python的解释器是一个读取并执行Python代码的程序。根据你的系统环境,你可以点击图标或者在命令行中输入python来运行解释器。它运行起来,你会看到类似这样的输出:
74 |
75 | ```python
76 | Python 3.4.0 (default, Jun 19 2015, 14:20:21)
77 | [GCC 4.8.2] on linux
78 | Type "help", "copyright", "credits" or "license" for more information.
79 | >>>
80 | ```
81 |
82 | The first three lines contain information about the interpreter and the operating system it’s running on, so it might be different for you. But you should check that the version number, which is 3.4.0 in this example, begins with 3, which indicates that you are running Python 3. If it begins with 2, you are running \(you guessed it\) Python 2.
83 |
84 | > 开头的三行包含了关于解释器和所在操作系统的信息,所以大家各自的情况可能有所不同。不过当你检查版本的时候,比如例子中的是3.4.0,使用3开头的,那就告诉你了,他运行的是Python3。你肯定也能猜到,如果开头的是2那就是Python2咯。
85 |
86 | The last line is a prompt that indicates that the interpreter is ready for you to enter code. If you type a line of code and hit Enter, the interpreter displays the result:
87 |
88 | > 最后一行那个是提示符,告诉你解释器已经就绪了,你可以输入代码了。如果你输入一行代码然后回车键,解释器就会显示结果了,如下所示:
89 |
90 | ```python
91 | >>> 1 + 1
92 | 2
93 | ```
94 |
95 | Now you’re ready to get started. From here on, I assume that you know how to start the Python interpreter and run code.
96 |
97 | > 现在你已经做好开始学习Python的准备了。现在我估计你应该已经知道怎么来启动Python解释器和运行Python代码了。
98 |
99 | ## 1.3 The first program 第一个程序
100 |
101 | Traditionally, the first program you write in a new language is called “Hello, World!” because all it does is display the words “Hello, World!”. In Python, it looks like this:
102 |
103 | > 传统意义上,大家学一门新编程语言要写的第一个程序都被叫做『Hello,World!』,因为这第一个程序就用来显示这个词组『Hello,World!』。在Python中,是这样实现的:
104 |
105 | ```python
106 | >>> print('Hello, World!')
107 | ```
108 |
109 | This is an example of a print statement, although it doesn’t’t actually print anything on paper. It displays a result on the screen. In this case, the result is the words `Hello, World!`
110 |
111 | > 这是一个打印语句的例子,虽然并没有往纸张上面进行实际的『打印』。这个程序把结果显示在屏幕上。结果就是输出了这个词组`Hello, World!`
112 |
113 | The quotation marks in the program mark the beginning and end of the text to be displayed; they don’t appear in the result.
114 |
115 | > 输出的文字前后在源代码中有引号;这些引号在输出的时候不显示。
116 |
117 | The parentheses indicate that print is a function. We’ll get to functions in Chapter 3.
118 |
119 | > 括号表明了print是一个函数。关于函数我们到第三章再讨论。
120 |
121 | In Python 2, the print statement is slightly different; it is not a function, so it doesn’t use parentheses.
122 |
123 | > 在Python2中,打印的语句有一点点不一样:print不是一个函数,所以就不用有括号了。
124 |
125 | ```python
126 | >>> print 'Hello, World!'
127 | ```
128 |
129 | This distinction will make more sense soon, but that’s enough to get started.
130 |
131 | > 这个区别以后会理解更深入,现在说这点就够了。
132 |
133 | ## 1.4 Arithmetic operators 运算符
134 |
135 | After “Hello, World”, the next step is arithmetic. Python provides operators, which are special symbols that represent computations like addition and multiplication.
136 |
137 | > 在『Hello,World!』之后,下一步就是运算了。Python提供了运算符,就是一些用来表示例如加法、乘法等运算的符号了。
138 |
139 | The operators +, -, and \* perform addition, subtraction, and multiplication, as in the following examples:
140 |
141 | > 运算符+,-和\*表示加法、减法和乘法,如下所示:
142 |
143 | ```python
144 | >>> 40 + 2
145 | 42
146 | >>> 43 - 1
147 | 42
148 | >>> 6 * 7
149 | 42
150 | ```
151 |
152 | The operator / performs division:
153 |
154 | > 运算符右斜杠/意味着除法:
155 |
156 | ```python
157 | >>> 84 / 2
158 | 42.0
159 | ```
160 |
161 | You might wonder why the result is 42.0 instead of 42. I’ll explain in the next section.
162 |
163 | > 你估计在纳闷为啥结果是42.0而不是42,这个下一章节我再解释。
164 |
165 | Finally, the operator \*\* performs exponentiation; that is, it raises a number to a power:
166 |
167 | > 最后,再说个运算符\*\*,它表示乘方,就是前一个数为底数,后一个数为指数的次幂运算:
168 |
169 | ```python
170 | >>> 6**2 + 6
171 | 42
172 | ```
173 |
174 | In some other languages, `^` is used for exponentiation, but in Python it is a bitwise operator called XOR. If you are not familiar with bitwise operators, the result will surprise you:
175 |
176 | > 在其他的一些编程语言中, `^`这个符号是乘方的意思,但在Python中这是一个位运算操作符叫做『异或』。要是你不熟悉位运算操作符,结果一定让你很惊讶:
177 |
178 | ```python
179 | >>> 6 ^ 2
180 | 4
181 | ```
182 |
183 | I won’t cover bitwise operators in this book, but you can read about them at [Wiki](http://wiki.python.org/moin/BitwiseOperators).
184 | 我在本书中不会涉及到位运算,但你可以在下面这个链接里面读一下来了解:[Wiki](http://wiki.python.org/moin/BitwiseOperators)。
185 |
186 | ## 1.5 Values and types 值和类型
187 |
188 | A value is one of the basic things a program works with, like a letter or a number. Some values we have seen so far are 2, 42.0, and 'Hello, World!'.
189 |
190 | > 值就是一个程序操作的基本对象之一,比如一个字母啊,或者数字。刚刚我们看到了一些值的例子了,比如2,42.0,还有那个字符串『Hello,World!』
191 |
192 | These values belong to different types: 2 is an integer, 42.0 is a floating-point number, and 'Hello, World!' is a string, so-called because the letters it contains are strung together.
193 |
194 | > 这些值属于不同的类型:2是一个整形值,42.0是浮点数,『Hello,World!』是字符串咯。之所以叫字符串就是因为有一串字符。(译者注:这本书的作者真心掰开揉碎地讲解每一个点啊,高中生甚至初中生都应该理解起来没有什么问题,所以大家用这本书来学编程绝对是最佳选择了。)
195 |
196 | If you are not sure what type a value has, the interpreter can tell you:
197 |
198 | > 如果你不确定一个值是什么类型呢,你可以让解释器来告诉你:
199 |
200 | ```python
201 | >>> type(2)
202 |
203 | >>> type(42.0)
204 |
205 | >>> type('Hello, World!')
206 |
207 | ```
208 |
209 | In these results, the word “class” is used in the sense of a category; a type is a category of values.
210 |
211 | > 在这些例子中,『class』这个字样表明这是一类,一种类型就是对值的一种划分。
212 |
213 | Not surprisingly, integers belong to the type int, strings belong to str and floating-point numbers belong to float.
214 |
215 | > 很自然了,整形的就是int了,字符串就是str了,浮点数就是float了。
216 |
217 | What about values like '2' and '42.0'? They look like numbers, but they are in quotation marks like strings.
218 |
219 | > 那'2' 和 '42.0'这种是啥呢?他们看着像是数字,但带了单引号了。
220 |
221 | ```python
222 | >>> type('2')
223 |
224 | >>> type('42.0')
225 |
226 | ```
227 |
228 | They’re strings.
229 |
230 | > 真相就是——他们也是字符串了。
231 |
232 | When you type a large integer, you might be tempted to use commas between groups of digits, as in 1,000,000. This is not a legal integer in Python, but it is legal:
233 |
234 | > 咱们现在输入一个大的整数,在中间用逗号分隔试试看,比如1,000,000,并不是Python中合乎语法的整形,但也被接受了:
235 |
236 | ```python
237 | >>> 1,000,000
238 | (1, 0, 0)
239 | ```
240 |
241 | That’s not what we expected at all! Python interprets 1,000,000 as a comma-separated sequence of integers. We’ll learn more about this kind of sequence later.
242 |
243 | > 出乎意料吧,Python把逗号当做了分隔三个整形数字的分隔符了。我们以后再对这种序列进行讨论。
244 |
245 | ## 1.6 Formal and natural languages 公式语言和自然语言
246 |
247 | Natural languages are the languages people speak, such as English, Spanish, and French. They were not designed by people \(although people try to impose some order on them\); they evolved naturally.
248 |
249 | > 自然语言就是人说的语言,比如英语、西班牙语、法语,当然包括中文了。他们往往都不是人主动去设计出来的(当然,人会试图去分析语言的规律),自然而然地发生演进。
250 |
251 | Formal languages are languages that are designed by people for specific applications. For example, the notation that mathematicians use is a formal language that is particularly good at denoting relationships among numbers and symbols. Chemists use a formal language to represent the chemical structure of molecules. And most importantly:
252 | Programming languages are formal languages that have been designed to express computations.
253 |
254 | > 公式语言是人们为了特定用途设计出来的。比如数学的符号就是一种公式语言,特别适合表达数字和符号只见的关系。化学家也用元素符号和化学方程式来表示分子的化学结构。要注意的是:
255 | > 编程语言是一种用来表达运算的公式语言。
256 |
257 | Formal languages tend to have strict syntax rules that govern the structure of statements. For example, in mathematics the statement 3 + 3 = 6 has correct syntax, but 3 + = 3 $ 6 does not. In chemistry H2O is a syntactically correct formula, but 2Zz is not.
258 |
259 | > 公式语言有严格的语法规则和对语句结构的要求。比如数学式3+3=6是正确的,而3+=3¥6就不是了。化学上H2O 是正确的化学式,而2Zz 就不是。
260 |
261 | Syntax rules come in two flavors, pertaining to tokens and structure. Tokens are the basic elements of the language, such as words, numbers, and chemical elements. One of the problems with 3 += 3 $ 6 is that $ is not a legal token in mathematics \(at least as far as I know\). Similarly, 2Zz is not legal because there is no element with the abbreviation Zz.
262 |
263 | > 语法规则体现在两个方面,代号和结构。 代号是语言的基础元素,比如单词、数字以及化学元素。3 += 3 $ 6这个式子数学上无意义的一个原因就是因为 $ 并不是数学上的符号 \(至少我所学的数学是没有这个符号的\)。类似地, 2Zz 也不对,因为没有一种化学元素的缩写是 Zz.
264 |
265 | The second type of syntax rule pertains to the way tokens are combined. The equation 3 += 3 is illegal because even though + and = are legal tokens, you can’t have one right after the other. Similarly, in a chemical formula the subscript comes after the element name, not before.
266 |
267 | > 第二个语法规则是代号必须有严格的组合结构。3 += 3这个式子数学上错误就因为虽然这些符号都是数学符号,但不能把加号等号放一起。类似地,化学方程式中要先写元素名字后写个数,而不是反着。
268 |
269 | This is @ well-structured Engli$h sentence with invalid t\*kens in it. This sentence all valid tokens has, but invalid structure with.
270 |
271 | > 这句英语的单词和结构都有错误,大家还是能看懂的哈。(译者注,作者故意这样写,来表明人类的自然语言容错率高。)
272 |
273 | When you read a sentence in English or a statement in a formal language, you have to figure out the structure \(although in a natural language you do this subconsciously\). This process is called parsing.
274 |
275 | > 你读一句英语或者公式语言中的语句时候,你必须搞清楚结构(虽然在自然语言中大家潜意识就能搞定了)。这就叫做解译。
276 |
277 | Although formal and natural languages have many features in common—tokens, structure, and syntax—there are some differences:
278 |
279 | > 虽然公式语言和自然语言有很多共同特征,比如代号、结构、语法这些元素,但差别还是显著的,比如:
280 |
281 | * ambiguity 二义性:
282 | Natural languages are full of ambiguity, which people deal with by using contextual clues and other information. Formal languages are designed to be nearly or completely unambiguous, which means that any statement has exactly one meaning, regardless of context.
283 | > 自然语言充满二义性,也就是歧义了,人们有时候用上下文线索或者其他信息来帮助处理这种情况。公式语言被设计为尽量不具有二义性,这就意味着一个语句往往只有唯一的一种含义,与上下文无关。
284 |
285 | * redundancy 冗余性:
286 | In order to make up for ambiguity and reduce misunderstandings, natural languages employ lots of redundancy. As a result, they are often verbose. Formal languages are less redundant and more concise.
287 | > 为了弥补歧义,减少误解,自然语言有很多冗余,结果就是经常有废话。公式语言要精简的多。
288 |
289 | * literalness 文字修辞:
290 | Natural languages are full of idiom and metaphor. If I say, “The penny dropped”, there is probably no penny and nothing dropping \(this idiom means that someone understood something after a period of confusion\). Formal languages mean exactly what they say.
291 | > 自然语言充满习语和隐喻等。比如我说 “The penny dropped”, 可能并不是字面意思说硬币掉了\(这个俚语意思是过了一会终于弄明白了\)。公式语言的意思严格精准。
292 |
293 | Because we all grow up speaking natural languages, it is sometimes hard to adjust to formal languages. The difference between formal and natural language is like the difference between poetry and prose, but more so:
294 |
295 | > 咱们大家都是说着自然语言长大的,要调节到公式语言有时候挺难的。这两者之间的差别有点像诗词和散文,但差别更大:
296 |
297 | * Poetry 诗词:
298 | Words are used for their sounds as well as for their meaning, and the whole poem together creates an effect or emotional response. Ambiguity is not only common but often deliberate.
299 |
300 | > 单词的运用要兼顾词义和押韵,诗的整体要有一定的意境或者情感上的共鸣。双关很常见,并且多是故意的。
301 |
302 | * Prose 散文:
303 | The literal meaning of words is more important, and the structure contributes more meaning. Prose is more amenable to analysis than poetry but still often ambiguous.
304 |
305 | > 文字意思更重要,结构也有重要作用。相比诗词更好理解,但也有一定的双关语歧义。
306 |
307 | * Programs 程序:
308 | The meaning of a computer program is unambiguous and literal, and can be understood entirely by analysis of the tokens and structure.
309 | > 计算机程序的意义必须是无歧义和文采修饰的,能完全用代号和结构的方式进行解析。
310 |
311 | Formal languages are more dense than natural languages, so it takes longer to read them. Also, the structure is important, so it is not always best to read from top to bottom, left to right. Instead, learn to parse the program in your head, identifying the tokens and interpreting the structure. Finally, the details matter. Small errors in spelling and punctuation, which you can get away with in natural languages, can make a big difference in a formal language.
312 |
313 | > 公式语言比自然语言要更加密集,读起来也需要更长时间。公式语言的结构也非常重要,所以从头到尾或者从左到右未必就是最佳方式。大家应该学着动脑来解译程序,分辨代号,解析结构。最后要注意的就是在公式语言中,细节特别特别重要。拼写和符号的小错误对于自然语言来说没什么,但对公式语言来说就能带来大问题。
314 |
315 | ## 1.7 Debugging 调试
316 |
317 | Programmers make mistakes. For whimsical reasons, programming errors are called bugs and the process of tracking them down is called debugging.
318 |
319 | > 程序员也会犯错的。由于很奇妙的原因,程序的错误被叫做bug,调试的过程就叫debug了。(译者注:一个传言是最早的计算机中经常有虫子进去导致短路之类的,清理虫子就成了常规调试的操作,流传至今。。。)
320 |
321 | Programming, and especially debugging, sometimes brings out strong emotions. If you are struggling with a difficult bug, you might feel angry, despondent, or embarrassed.
322 |
323 | > 编程,尤其是调试的过程,有时候会给人带来强烈的挫败感。面对特别复杂的状况,你可能就感到愤怒、压抑,或者特别难受。
324 |
325 | There is evidence that people naturally respond to computers as if they were people. When they work well, we think of them as teammates, and when they are obstinate or rude, we respond to them the same way we respond to rude, obstinate people \(Reeves and Nass, The Media Equation: How People Treat Computers, Television, and New Media Like Real People and Places\).
326 |
327 | > 别担心,这些都是正常人对计算机的正常反应。计算机工作正常了,我们会觉得他们像是队友一样;一旦工作出错了,对我们很粗暴,我们对他们的反应就像是对待粗暴可恨的人一样(参考Reeves和Nass,The Media Equation: How People Treat Computers, Television, and New Media Like Real People and Places)。
328 |
329 | Preparing for these reactions might help you deal with them. One approach is to think of the computer, as an employee with certain strengths, like speed and precision, and particular weaknesses, like lack of empathy and inability to grasp the big picture.
330 |
331 | > 为这些反应做好心理准备,这样你在遇到类似情况就更好应对了。我们也可以把计算机当做一个有一定优点但也有特定缺陷的员工,比如速度快精度高,但缺乏共鸣和应对大场面的能力。
332 |
333 | Your job is to be a good manager: find ways to take advantage of the strengths and mitigate the weaknesses. And find ways to use your emotions to engage with the problem, without letting your reactions interfere with your ability to work effectively.
334 |
335 | > 你的工作就是做个好的经理人:尽量充分利用员工优势并降低他们缺陷的作用。然后想办法把你的情绪用在解决问题上,而不要让过激的反应干扰工作效率。
336 |
337 | Learning to debug can be frustrating, but it is a valuable skill that is useful for many activities beyond programming. At the end of each chapter there is a section, like this one, with my suggestions for debugging. I hope they help!
338 |
339 | > 调试的过程挺烦人的,但这个本领很有价值,而且在编程之外的其他领域都有用武之地。在每一章的末尾,都会有这样的一段,我会给出一些关于调试方面的建议。希望能帮到大家!
340 |
341 | 1.8 Glossary 术语列表
342 | problem solving:
343 | The process of formulating a problem, finding a solution, and expressing it.
344 |
345 | > 问题解决:将问题方程化,找到解决方案,并表达出来的过程。
346 |
347 | high-level language:
348 | A programming language like Python that is designed to be easy for humans to read and write.
349 |
350 | > 高级语言:例如Python这样的编程语言,设计初衷为易于被人阅读和书写。
351 |
352 | low-level language:
353 | A programming language that is designed to be easy for a computer to run; also called “machine language” or “assembly language”.
354 |
355 | > 低级语言:设计初衷为易于被计算机运行的语言,比如机器语言和汇编语言。
356 |
357 | portability:
358 | A property of a program that can run on more than one kind of computer.
359 |
360 | > 可移植性:程序能运行于多种平台的特性。
361 | > interpreter:
362 |
363 | A program that reads another program and executes it
364 |
365 | > 解释器:一边读取一边执行代码的程序。
366 |
367 | prompt:
368 | Characters displayed by the interpreter to indicate that it is ready to take input from the user.
369 |
370 | > 提示符:解释器显示的,提醒用户准备就绪,随时可以输入。
371 |
372 | program:
373 | A set of instructions that specifies a computation.
374 |
375 | > 程序:进行一种特定运算的一系列指令。
376 |
377 | print statement:
378 | An instruction that causes the Python interpreter to display a value on the screen.
379 |
380 | > 打印语句:让Python解释器输出值到屏幕的指令。
381 |
382 | operator:
383 | A special symbol that represents a simple computation like addition, multiplication, or string concatenation.
384 |
385 | > 运算符(操作符):一系列特殊的符号,表示一些简单的运算,比如加减乘除或者字符串操作。
386 |
387 | value:
388 | One of the basic units of data, like a number or string, that a program manipulates.
389 |
390 | > 值:数据的基本组成单元,比如数字或者字符串,是程序处理的对象。
391 |
392 | type:
393 | A category of values. The types we have seen so far are integers \(typeint\), floating-point numbers \(type float\), and strings \(type str\).
394 |
395 | > 类型:对值的分类,大家刚刚接触到的有整形int,浮点数float,以及字符串str。
396 | > integer:
397 | > A type that represents whole numbers.
398 | > 整形:就是整数咯。
399 |
400 | floating-point:
401 | A type that represents numbers with fractional parts.
402 |
403 | > 浮点数:简单说,就是有小数点的数了。
404 |
405 | string:
406 | A type that represents sequences of characters.
407 |
408 | > 字符串:一串有序的字符了。
409 |
410 | natural language:
411 | Any one of the languages that people speak that evolved naturally.
412 |
413 | > 自然语言:人们说的语言,自然地演化。
414 |
415 | formal language:
416 | Any one of the languages that people have designed for specific purposes, such as representing mathematical ideas or computer programs; all programming languages are formal languages.
417 |
418 | > 公式语言:人为设计的用于特定用途的语言,比如数学用途或者计算机编程用的;所有编程语言都是公式语言。
419 |
420 | token:
421 | One of the basic elements of the syntactic structure of a program, analogous to a word in a natural language.
422 |
423 | > 代号:程序结构中的一种基本元素,相当于自然语言中的单词。
424 |
425 | syntax:
426 | The rules that govern the structure of a program.
427 |
428 | > 语法:程序语言结构的规则。
429 |
430 | parse:
431 | To examine a program and analyze the syntactic structure.
432 |
433 | > 解译:理解程序并分析语法结构的过程。
434 |
435 | bug:
436 | An error in a program.
437 |
438 | > Bug:程序的错误。
439 |
440 | debugging:
441 | The process of finding and correcting bugs.
442 |
443 | > 调试(debug):搜索和改正程序错误的过程。
444 |
445 | ## 1.9 Exercises 练习
446 |
447 | ### Exercise 1 练习1
448 |
449 | It is a good idea to read this book in front of a computer so you can try out the examples as you go.
450 |
451 | > 你读这本书的同时最好手边有台电脑,这样你就能把样例在电脑上随时运行来看看效果了。
452 |
453 | Whenever you are experimenting with a new feature, you should try to make mistakes. For example, in the “Hello, world!” program, what happens if you leave out one of the quotation marks? What if you leave out both? What if you spell print wrong?
454 |
455 | > 无论你学任何一种新功能的时候,都可以试着犯点错误。比如就在这个『Hello,World!』程序,你可以试试去掉一个引号会怎么样,都去掉会怎么样,print这个单词拼错了会怎么样等等。
456 |
457 | This kind of experiment helps you remember what you read; it also helps when you are programming, because you get to know what the error messages mean. It is better to make mistakes now and on purpose than later and accidentally.
458 |
459 | > 这种尝试能让你对读到的内容有更深刻的记忆;也有助于你编程,因为你在编程的时候也得知道调试信息的意思。所以最好现在就故意犯些错误来看看,比以后毫无准备地遇到要好多了。
460 |
461 | 1. In a print statement, what happens if you leave out one of the parentheses, or both?
462 |
463 | > 在print语句后面的括号去掉一个或者两个,看看会怎么样?
464 |
465 | 2. If you are trying to print a string, what happens if you leave out one of the quotation marks, or both?
466 |
467 | > Print字符串的时候如果你丢掉一个引号或者两个引号试试看会如何?
468 |
469 | 3. You can use a minus sign to make a negative number like -2. What happens if you put a plus sign before a number? What about 2++2?
470 |
471 | > 输入一个负数试试,比如-2。然后再试试在数字前面添加加号会怎么样?比如2++2。
472 |
473 | 4. In math notation, leading zeros are ok, as in 02. What happens if you try this in Python?
474 |
475 | > 数学上计数用零开头是可以得,比如02,在Python下面试试会怎样?
476 |
477 | 5. What happens if you have two values with no operator between them?
478 |
479 | > 两个值中间没有运算符会怎么样?
480 |
481 |
482 |
483 |
--------------------------------------------------------------------------------
/ThinkPython-15.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 15
2 | Date: 2016-1-2
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 15 Classes and objects 类和对象
7 |
8 |
9 |
10 | At this point you know how to use functions to organize code and built-in types to organize data. The next step is to learn “object-oriented programming”, which uses programmer-defined types to organize both code and data. Object-oriented programming is a big topic; it will take a few chapters to get there.
11 | Code examples from this chapter are available from [Here](http://thinkpython2.com/code/Point1.py); solutions to the exercises are available from [Here](http://thinkpython2.com/code/Point1_soln.py).
12 | >到目前位置,你应该已经知道如何用函数来整理代码,以及用内置类型来组织数据了。接下来的一步就是要学习『面向对象编程』了,这种编程方法中,用户可以自定义类型来同时对代码和数据进行整理。面向对象编程是一个很大的题目;要有好几章才能讲出个大概。
13 | >本章的样例代码可以在[这里](http://thinkpython2.com/code/Point1.py)来下载,练习题对应的样例代码可以在[这里](http://thinkpython2.com/code/Point1_soln.py)下载。
14 |
15 |
16 |
17 | ##15.1 Programmer-defined types 用户自定义类型
18 |
19 |
20 |
21 |
22 |
23 | We have used many of Python’s built-in types; now we are going to define a new type. As an example, we will create a type called Point that represents a point in two-dimensional space.
24 | >我们已经用过很多 Python 的内置类型了;现在我们就要来定义一个新的类型了。作为样例,我们会创建一个叫 Point 的类,用于表示一个二维空间中的点。
25 |
26 |
27 |
28 | In mathematical notation, points are often written in parentheses with a comma separating the coordinates. For example, (0,0) represents the origin, and (x,y) represents the point x units to the right and y units up from the origin.
29 | >数学符号上对点的表述一般是一个括号内有两个坐标,坐标用逗号分隔开。比如,(0,0)就表示为原点,(x,y)就表示了该点从原点向右偏移 x,向上偏移 y。
30 |
31 |
32 |
33 | There are several ways we might represent points in Python:
34 | >我们可以用好几种方法来在 Python 中表示一个点:
35 |
36 | • We could store the coordinates separately in two variables, x and y.
37 | >我们可以把坐标存储成两个单独的值,x 和 y。
38 |
39 | • We could store the coordinates as elements in a list or tuple.
40 | >还可以把坐标存储成列表或者元组的元素。
41 |
42 | • We could create a new type to represent points as objects.
43 | >还可以创建一个新的类型来用对象表示点。
44 |
45 |
46 |
47 | Creating a new type is more complicated than the other options, but it has advantages that will be apparent soon.
48 | >创建新的类型要比其他方法更复杂一点,不过也有一些优势,等会我们就会发现了。
49 |
50 |
51 |
52 | A programmer-defined type is also called a class. A class definition looks like this:
53 | >用户自定义的类型也被叫做一个类。一个类的定义大概是如下所示的样子:
54 |
55 | ```Python
56 | class Point:
57 | """Represents a point in 2-D space."""
58 | ```
59 |
60 |
61 |
62 | The header indicates that the new class is called Point. The body is a docstring that explains what the class is for. You can define variables and methods inside a class definition, but we will get back to that later.
63 | >头部代码的意思是表示新建的类名字叫 Point。然后类的体内有一个文档字符串,解释类的用途。在类的定义内部可以定义各种变量和方法,等会再来详细学习一下这些内容哈。
64 |
65 |
66 |
67 | Defining a class named Point creates a class object.
68 | >声明一个名为 Point 的类,就可以创建该类的一个对象。
69 |
70 |
71 | ```Python
72 | >>> Point
73 |
74 | ```
75 |
76 |
77 |
78 | Because Point is defined at the top level, its “full name” is __main__.Point.
79 | >因为 Point 是在顶层位置定义的,所以全名就是__main__.Point。
80 |
81 |
82 |
83 | The class object is like a factory for creating objects. To create a Point, you call Point as if it were a function.
84 | >类的对象就像是一个创建对象的工厂。要创建一个 Point,就可以像调用函数一样调用 Point。
85 |
86 |
87 | ```Python
88 | >>> blank = Point()
89 | >>> blank
90 | <__main__.Point object at 0xb7e9d3ac>
91 | ```
92 |
93 |
94 | The return value is a reference to a Point object, which we assign to blank.
95 | Creating a new object is called instantiation, and the object is an instance of the class.
96 | >返回值是到一个 Point 对象的引用,刚刚赋值为空白了。
97 | >创建一个新的对象也叫做实例化,这个对象就是类的一个实例。
98 |
99 |
100 | When you print an instance, Python tells you what class it belongs to and where it is stored in memory (the prefix 0x means that the following number is in hexadecimal).
101 | >用 Print 输出一个实例的时候,Python 会告诉你该实例所属的类,以及在内存中存储的位置(前缀为0x 意味着下面的这些数值是十六进制的。)
102 |
103 |
104 |
105 | Every object is an instance of some class, so “object” and “instance” are interchangeable. But in this chapter I use “instance” to indicate that I am talking about a programmer-defined type.
106 | >每一个对象都是某一个类的一个实例,所以『对象』和『实例』可以互换来使用。不过本章我还是都使用『实例』这个词,这样就更能体现出咱们在谈论的是用户定义的类型。
107 |
108 |
109 |
110 |
111 | ##15.2 Attributes 属性
112 |
113 |
114 |
115 | You can assign values to an instance using dot notation:
116 | >用点号可以给实例进行赋值:
117 |
118 |
119 | ```Python
120 | >>> blank.x = 3.0
121 | >>> blank.y = 4.0
122 | ```
123 |
124 |
125 |
126 |
127 |
128 |
129 | This syntax is similar to the syntax for selecting a variable from a module, such as math.pi or string.whitespace. In this case, though, we are assigning values to named elements of an object. These elements are called attributes.
130 | >这一语法形式就和从模块中选取变量的语法是相似的,比如 math.pi 或者 string.whitespace。然而在本章这种情况下,我们用点号实现的是对一个对象中某些特定名称的元素进行赋值。这些元素也叫做属性。
131 |
132 |
133 | As a noun, “AT-trib-ute” is pronounced with emphasis on the first syllable, as opposed to “a-TRIB-ute”, which is a verb.
134 | >『Attribute』作为名词的发音要把重音放在第一个音节,而做动词的时候是重音放到第二音节。
135 |
136 |
137 | The following diagram shows the result of these assignments. A state diagram that shows an object and its attributes is called an object diagram; see Figure 15.1.
138 | >下面的图表展示了上面这些赋值的结果。用于展示一个类及其属性的状态图也叫做类图;比如图15.1就是一例。
139 |
140 | ________________________________________
141 | 
142 | Figure 15.1: Object diagram.
143 | ________________________________________
144 |
145 |
146 |
147 |
148 |
149 | The variable blank refers to a Point object, which contains two attributes. Each attribute refers to a floating-point number.
150 | >变量 blank 指代的是一个 Point 对象,该对象包含两个属性。每个属性都指代了一个浮点数。
151 |
152 |
153 | You can read the value of an attribute using the same syntax:
154 | >读取属性值可以用如下这样的语法:
155 |
156 |
157 | ```Python
158 | >>> blank.y
159 | 4.0
160 | >>> x = blank.x
161 | >>> x
162 | 3.0
163 | ```
164 |
165 |
166 |
167 | The expression blank.x means, “Go to the object blank refers to and get the value of x.” In the example, we assign that value to a variable named x. There is no conflict between the variable x and the attribute x.
168 | >这里的表达式 blank.x 的意思是,『到 blank 所指代的对象中,读取 x 的值。』在这个例子中,我们把这个值赋值给一个名为 x 的变量。这里的变量 x 和类的属性x 并不冲突。
169 |
170 |
171 |
172 | You can use dot notation as part of any expression. For example:
173 | >点号可以随意在任意表达式中使用。比如下面这个例子:
174 |
175 | ```Python
176 | >>> '(%g, %g)' % (blank.x, blank.y)
177 | '(3.0, 4.0)'
178 | >>> distance = math.sqrt(blank.x**2 + blank.y**2)
179 | >>> distance
180 | 5.0
181 | ```
182 |
183 |
184 |
185 |
186 |
187 | You can pass an instance as an argument in the usual way. For example:
188 | >你还可以把实例作为一个参数来使用。比如下面这样:
189 |
190 |
191 |
192 | ```Python
193 | def print_point(p):
194 | print('(%g, %g)' % (p.x, p.y))
195 | ```
196 |
197 |
198 |
199 |
200 |
201 |
202 | print_point takes a point as an argument and displays it in mathematical notation. To invoke it, you can pass blank as an argument:
203 | >print_point 这个函数就接收了一个点作为参数,然后显示点的数值位置。你可以把刚刚那个 blank 作为参数传过去来试试:
204 |
205 |
206 |
207 | ```Python
208 | >>> print_point(blank)
209 | (3.0, 4.0)
210 | ```
211 |
212 |
213 |
214 | Inside the function, p is an alias for blank, so if the function modifies p, blank changes.
215 | >在函数内部,p 是blank 的一个别名,所以如果函数内部对 p 进行了修改,blank 也会发生相应的改变。
216 |
217 |
218 |
219 | As an exercise, write a function called distance_between_points that takes two Points as arguments and returns the distance between them.
220 | >做个练习,写一个名为 distance_between_points 的函数,接收两个点作为参数,然后返回两点之间的距离。
221 |
222 |
223 |
224 |
225 |
226 | ##15.3 Rectangles 矩形
227 |
228 |
229 |
230 | Sometimes it is obvious what the attributes of an object should be, but other times you have to make decisions. For example, imagine you are designing a class to represent rectangles. What attributes would you use to specify the location and size of a rectangle? You can ignore angle; to keep things simple, assume that the rectangle is either vertical or horizontal.
231 | >有时候一个类中的属性应该如何设置是很明显的,不过有的时候就得好好考虑一下了。比如,假设你要设计一个表示矩形的类。你要用什么样的属性来确定一个矩形的位置和大小呢?可以忽略角度;来让情况更简单一些,就只考虑矩形是横向的或者纵向的。
232 |
233 |
234 |
235 |
236 | There are at least two possibilities:
237 | >至少有两种方案备选:
238 |
239 | • You could specify one corner of the rectangle (or the center), the width, and the height.
240 | >确定矩形的一个顶点(或者中心)所在位置,还有宽度和高度。
241 |
242 |
243 | • You could specify two opposing corners.
244 | >确定对角线上的两个顶点所在位置。
245 |
246 |
247 |
248 | At this point it is hard to say whether either is better than the other, so we’ll implement the first one, just as an example.
249 | >现在还很难说这两者哪一个更好,那么咱们先用第一个方案来做个例子。
250 |
251 | Here is the class definition:
252 | >下面就是类的定义:
253 |
254 |
255 | ```Python
256 | class Rectangle:
257 | """Represents a rectangle.
258 | attributes: width, height, corner.
259 | """
260 | ```
261 |
262 |
263 | The docstring lists the attributes: width and height are numbers; corner is a Point object that specifies the lower-left corner.
264 | >文档字符串中列出了属性:width 和 height 是数值;corner 是一个点对象,用来表示左下角顶点。
265 |
266 |
267 |
268 | To represent a rectangle, you have to instantiate a Rectangle object and assign values to the attributes:
269 | >要表示一个矩形,必须初始化一个矩形对象,然后对其属性进行赋值:
270 |
271 | ```Python
272 | box = Rectangle()
273 | box.width = 100.0
274 | box.height = 200.0
275 | box.corner = Point()
276 | box.corner.x = 0.0
277 | box.corner.y = 0.0
278 | ```
279 |
280 |
281 |
282 | The expression box.corner.x means, “Go to the object box refers to and select the attribute named corner; then go to that object and select the attribute named x.”
283 | >表达式 box.corner.x 的意思是,『到 box 指代的对象中,选择名为 corner 的属性;然后到这个点对象中,选取名为 x 的属性值。』
284 |
285 |
286 |
287 |
288 | ________________________________________
289 | 
290 | Figure 15.2: Object diagram.
291 | ________________________________________
292 |
293 | Figure 15.2 shows the state of this object. An object that is an attribute of another object is embedded.
294 | >图15.2展示了这个对象的状态图。一个类去作为另外一个类的属性,就叫做嵌入。
295 |
296 |
297 |
298 |
299 |
300 | ##15.4 Instances as return values 多个实例作返回值
301 |
302 |
303 |
304 |
305 | Functions can return instances. For example, find_center takes a Rectangle as an argument and returns a Point that contains the coordinates of the center of the Rectangle:
306 | >函数亏返回实例。比如 find_center 就接收一个 Rectangle (矩阵)对象作为参数,然后以一个Point(点)对象的形式返回矩形中心位置的坐标所在点:
307 |
308 |
309 | ```Python
310 | def find_center(rect):
311 | p = Point()
312 | p.x = rect.corner.x + rect.width/2
313 | p.y = rect.corner.y + rect.height/2
314 | return p
315 | ```
316 |
317 |
318 | Here is an example that passes box as an argument and assigns the resulting Point to center:
319 | >下面这个例子中,box 作为一个参数传递给了 find_center 函数,然后结果赋值给了点 center:
320 |
321 |
322 |
323 | ```Python
324 | >>> center = find_center(box)
325 | >>> print_point(center)
326 | (50, 100)
327 | ```
328 |
329 |
330 |
331 | ##15.5 Objects are mutable 对象可以修改
332 |
333 |
334 |
335 | You can change the state of an object by making an assignment to one of its attributes. For example, to change the size of a rectangle without changing its position, you can modify the values of width and height:
336 | >通过对一个对象的属性进行赋值就可以修改该对象的状态了。比如,要改变一个举行的大小而不改变位置,就可以只修改宽度和高度,如下所示:
337 |
338 |
339 | ```Python
340 | box.width = box.width + 50
341 | box.height = box.height + 100
342 | ```
343 |
344 |
345 |
346 | You can also write functions that modify objects. For example, grow_rectangle takes a Rectangle object and two numbers, dwidth and dheight, and adds the numbers to the width and height of the rectangle:
347 | >你还可以写专门的函数来修改对象。比如grow_rectangle这个函数就接收一个矩形对象和dwidth 与 dheight两个数值,然后把这两个数值加到矩形的宽度和高度值上。
348 |
349 |
350 |
351 | ```Python
352 | def grow_rectangle(rect, dwidth, dheight):
353 | rect.width += dwidth
354 | rect.height += dheight
355 | ```
356 |
357 |
358 |
359 |
360 | Here is an example that demonstrates the effect:
361 | >下面的例子展示了具体的效果:
362 |
363 |
364 | ```Python
365 | >>> box.width, box.height
366 | (150.0, 300.0)
367 | >>> grow_rectangle(box, 50, 100)
368 | >>> box.width, box.height
369 | (200.0, 400.0)
370 | ```
371 |
372 |
373 |
374 | Inside the function, rect is an alias for box, so when the function modifies rect,box changes.
375 | >在函数的内部,rect 是 box 的一个别名,所以当函数修改了 rect 的时候,box 就得到了相应的修改。
376 |
377 |
378 | As an exercise, write a function named move_rectangle that takes a Rectangle and two numbers named dx and dy. It should change the location of the rectangle by adding dx to the x coordinate of corner and adding dy to the y coordinate of corner.
379 | >做个练习,写一个名为 move_rectangle 的函数,接收一个矩形和dx 与 dy 两个数值。函数要改变矩形所在位置,具体的改变方法为对左下角顶点坐标的 x 和 y 分别加上 dx 和 dy 的值。
380 |
381 |
382 |
383 | ##15.6 Copying 复制
384 |
385 |
386 |
387 | Aliasing can make a program difficult to read because changes in one place might have unexpected effects in another place. It is hard to keep track of all the variables that might refer to a given object.
388 | >别名有可能让程序读起来有困难,因为在一个位置做出的修改有可能导致另外一个位置发生不可预知的情况。这样也很难去追踪指向一个对象的所有变量。
389 |
390 |
391 | Copying an object is often an alternative to aliasing. The copy module contains a function called copy that can duplicate any object:
392 | >所以就可以不用别名,而用复制对象的方法。copy 模块包含了一个名叫 copy 的函数,可以复制任意对象:
393 |
394 |
395 |
396 | ```Python
397 | >>> p1 = Point()
398 | >>> p1.x = 3.0
399 | >>> p1.y = 4.0
400 | >>> import copy
401 | >>> p2 = copy.copy(p1)
402 | ```
403 |
404 |
405 |
406 |
407 | p1 and p2 contain the same data, but they are not the same Point.
408 | >p1和 p2包含的数据是相同的,但并不是同一个点对象。
409 |
410 |
411 |
412 | ```Python
413 | >>> print_point(p1)
414 | (3, 4)
415 | >>> print_point(p2)
416 | (3, 4)
417 | >>> p1 is p2
418 | False
419 | >>> p1 == p2
420 | False
421 | ```
422 |
423 |
424 | The is operator indicates that p1 and p2 are not the same object, which is what we expected. But you might have expected == to yield True because these points contain the same data. In that case, you will be disappointed to learn that for instances, the default behavior of the == operator is the same as the is operator; it checks object identity, not object equivalence. That’s because for programmer-defined types, Python doesn’t know what should be considered equivalent. At least, not yet.
425 | >is 运算符表明 p1和 p2不是同一个对象,这就是我们所预料的。但你可能本想着是==运算符应该得到的是 True 因为这两个点包含的数据是一样的。这样的话你就会很失望地发现对于实例来说,==运算符的默认行为就跟 is 运算符是一样的;它也还是检查对象的身份,而不是对象的相等性。这是因为你用的是用户自定义的类型,Python 不值得如何去衡量是否相等。至少是现在还不能。
426 | >(译者注:==运算符的实现需要运算符重载,也就是多态的一种,来实现,也就是对用户自定义类型,需要用户自定义运算符,而不能简单地继续用内置运算符。因为自定义类型的运算是 Python 没法确定的,得用户自己来确定。)
427 |
428 |
429 |
430 |
431 | If you use copy.copy to duplicate a Rectangle, you will find that it copies the Rectangle object but not the embedded Point.
432 | >如果你用 copy.copy 复制了一个矩形,你会发现该函数复制了矩形对象,但没有复制内嵌的点对象。
433 |
434 |
435 |
436 | ```Python
437 | >>> box2 = copy.copy(box)
438 | >>> box2 is box
439 | False
440 | >>> box2.corner is box.corner
441 | True
442 | ```
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 | ________________________________________
451 | 
452 | Figure 15.3: Object diagram.
453 | ________________________________________
454 |
455 |
456 |
457 |
458 | Figure 15.3 shows what the object diagram looks like. This operation is called a shallow copy because it copies the object and any references it contains, but not the embedded objects.
459 | >图15.3展示了此时的类图的情况。这种运算叫做浅复制,因为复制了对象与对象内包含的所有引用,但不复制内嵌的对象。
460 |
461 |
462 |
463 | For most applications, this is not what you want. In this example, invoking grow_rectangle on one of the Rectangles would not affect the other, but invoking move_rectangle on either would affect both! This behavior is confusing and error-prone.
464 | >对于大多数应用来说,这并不是你的本来目的。在本节的样例中,对复制过的一个矩形进行 grow_rrectangle 函数运算,并不会影响另外一个,但使用 move_rectangle 就会对两个都有影响!这种行为就很让人疑惑,也容易带来错误。
465 |
466 |
467 |
468 |
469 | Fortunately, the copy module provides a method named deepcopy that copies not only the object but also the objects it refers to, and the objects they refer to, and so on. You will not be surprised to learn that this operation is called a deep copy.
470 | >所幸的是 copy 模块还提供了一个名为 deepcopy (深复制)的方法,这样就能把内嵌的对象也复制了。你肯定不会奇怪了,这种运算就叫深复制了。
471 |
472 |
473 |
474 |
475 | ```Python
476 | >>> box3 = copy.deepcopy(box)
477 | >>> box3 is box
478 | False
479 | >>> box3.corner is box.corner
480 | False
481 | ```
482 |
483 |
484 |
485 | box3 and box are completely separate objects.
486 | As an exercise, write a version of move_rectangle that creates and returns a new Rectangle instead of modifying the old one.
487 | >box3和 box 就是完全隔绝开,没有公用内嵌对象,彻底不会相互干扰的两个对象了。
488 | >做个联系吧,写一个新版本的 move_rectangle,创建并返回一个新的矩形,而不是修改旧有的矩形。
489 |
490 |
491 |
492 | ##15.7 Debugging 调试
493 |
494 |
495 |
496 | When you start working with objects, you are likely to encounter some new exceptions. If you try to access an attribute that doesn’t exist, you get an AttributeError:
497 | >当你开始使用对象的时候,你就容易遇到一些新的异常。如果你试图读取一个不存在的属性,就会得到一个属性错误AttributeError:
498 |
499 |
500 | ```Python
501 | >>> p = Point()
502 | >>> p.x = 3
503 | >>> p.y = 4
504 | >>> p.z
505 | AttributeError: Point instance has no attribute 'z'
506 | ```
507 |
508 |
509 |
510 |
511 | If you are not sure what type an object is, you can ask:
512 | >如果不确定一个对象是什么类型,可以『问』一下:
513 |
514 |
515 |
516 | ```Python
517 | >>> type(p)
518 |
519 | ```
520 |
521 |
522 |
523 | You can also use isinstance to check whether an object is an instance of a class:
524 | >还可以用 isinstance 函数来检查一下一个对象是否为某一个类的实例:
525 |
526 |
527 |
528 | ```Python
529 | >>> isinstance(p, Point)
530 | True
531 | ```
532 |
533 |
534 |
535 | If you are not sure whether an object has a particular attribute, you can use the built-in function hasattr:
536 | >如果不确定某一对象是否有一个特定的属性,可以用内置函数 hasattr:
537 |
538 |
539 |
540 | ```Python
541 | >>> hasattr(p, 'x')
542 | True
543 | >>> hasattr(p, 'z')
544 | False
545 | ```
546 |
547 |
548 |
549 |
550 |
551 |
552 | The first argument can be any object; the second argument is a string that contains the name of the attribute.
553 | >hasattr 的第一个参数可以是任意一个对象;第二个参数是一个字符串,就是要判断是否存在的属性名字。
554 |
555 |
556 |
557 | You can also use a try statement to see if the object has the attributes you need:
558 | >用 try 语句也可以试验一个对象是否有你需要的属性:
559 |
560 |
561 | ```language
562 | try:
563 | x = p.x
564 | except AttributeError:
565 | x = 0
566 | ```
567 |
568 |
569 |
570 | This approach can make it easier to write functions that work with different types; more on that topic is coming up in Section 17.9.
571 | >这样写一些处理不同类型变量的函数就更容易了;关于这一话题的更多内容会在17.9中展开。
572 |
573 |
574 |
575 | ##15.8 Glossary 术语列表
576 |
577 |
578 | class:
579 | A programmer-defined type. A class definition creates a new class object.
580 | >类:用户定义的类型。一个类的声明建立了一个新的类的对象。
581 |
582 |
583 |
584 | class object:
585 | An object that contains information about a programmer-defined type. The class object can be used to create instances of the type.
586 | >类的对象:包含了用户自定义类型相关信息的一个对象。可以用于创建类的一个实例。
587 |
588 |
589 |
590 | instance:
591 | An object that belongs to a class.
592 | >实例:术语某一个类的一个对象。
593 |
594 |
595 | instantiate:
596 | To create a new object.
597 | >实例化:创建一个新的对象。
598 |
599 |
600 | attribute:
601 | One of the named values associated with an object.
602 | >属性:一个对象内附属的数值的名字。
603 |
604 |
605 | embedded object:
606 | An object that is stored as an attribute of another object.
607 | >内嵌对象:一个对象作为属性存储在另一个对象内。
608 |
609 |
610 |
611 | shallow copy:
612 | To copy the contents of an object, including any references to embedded objects; implemented by the copy function in the copy module.
613 | >浅复制:复制一个对象中除了内嵌对象之外的所有引用;通过 copy 模块的 copy 函数来实现。
614 |
615 |
616 |
617 | deep copy:
618 | To copy the contents of an object as well as any embedded objects, and any objects embedded in them, and so on; implemented by the deepcopy function in the copy module.
619 | >深复制:复制一个对象的所有内容,包括内嵌对象,以及内嵌对象中的所有内嵌对象等等;通过 copy 模块的 deepcopy 函数来实现。
620 |
621 |
622 |
623 | object diagram:
624 | A diagram that shows objects, their attributes, and the values of the attributes.
625 | >类图:一种图解,用于展示类与类中的属性以及属性的值。
626 |
627 |
628 |
629 | ##15.9 Exercises 练习
630 |
631 |
632 |
633 |
634 | ###Exercise 1 练习1
635 |
636 |
637 |
638 | Write a definition for a class named Circle with attributes center and radius, where center is a Point object and radius is a number.
639 | >写一个名为 Circle 的类的定义,属性为圆心center和半径radius,center 是一个点对象,半径是一个数值。
640 |
641 |
642 |
643 | Instantiate a Circle object that represents a circle with its center at (150, 100) and radius 75.
644 | >实例化一个 Circle 的对象,表示一个圆,圆心在(150,100),半径为75。
645 |
646 |
647 |
648 | Write a function named point_in_circle that takes a Circle and a Point and returns True if the Point lies in or on the boundary of the circle.
649 | >写一个名为 point_in_circle 的函数,接收一个 Circle 和一个 Point 对象作为参数,如果点在圆内或者圆的线上就返回True。
650 |
651 |
652 | Write a function named rect_in_circle that takes a Circle and a Rectangle and returns True if the Rectangle lies entirely in or on the boundary of the circle.
653 | >写一个名为 rect_in_circle 的函数,接收一个 Circle 和一个 Rectangle 对象作为参数,如果矩形的边都内含或者内切在圆内,就返回 True。
654 |
655 |
656 | Write a function named rect_circle_overlap that takes a Circle and a Rectangle and returns True if any of the corners of the Rectangle fall inside the circle. Or as a more challenging version, return True if any part of the Rectangle falls inside the circle.
657 | >写一个名为 rect_circle_overlap 的函数,接收一个 Circle 和一个 Rectangle 对象作为参数,如果矩形任意一个顶点在圆内就返回 True。或者写个更有挑战性的版本,如果矩形有任意部分包含在圆内就返回 True。
658 |
659 |
660 | [Solution](http://thinkpython2.com/code/Circle.py).
661 | >[样例代码](http://thinkpython2.com/code/Circle.py)。
662 |
663 |
664 |
665 | ###Exercise 2 练习2
666 |
667 |
668 |
669 | Write a function called draw_rect that takes a Turtle object and a Rectangle and uses the Turtle to draw the Rectangle. See Chapter 4 for examples using Turtle objects.
670 | >写一个名为 draw_rect的函数,接收一个 Turtle 对象和一个 Rectangle 对象作为参数,用 Turtle 画出这个矩形。可以参考一下第四章对 Turtle 对象使用的样例。
671 |
672 |
673 |
674 |
675 | Write a function called draw_circle that takes a Turtle and a Circle and draws the Circle.
676 | [Solution](http://thinkpython2.com/code/draw.py).
677 | >写一个名为 draw_circle 的函数,接收一个 Turtle 对象和一个 Circle 对象,画个圆这次。
678 | >[样例代码](http://thinkpython2.com/code/draw.py)。
679 |
680 |
681 |
--------------------------------------------------------------------------------
/ThinkPython-16.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 16
2 | Date: 2016-1-21
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 16 Classes and functions 类和函数
7 |
8 | Now that we know how to create new types, the next step is to write functions that take programmer-defined objects as parameters and return them as results. In this chapter I also present “functional programming style” and two new program development plans.
9 | >现在我们已经知道如何创建新类型了,下一步就要写一些函数了,这些函数用自定义类型做参数和返回值。在本章中还提供了一种函数式编程的模式,以及两种新的程序开发规划方式。
10 |
11 |
12 | Code examples from this chapter are available from [Here](http://thinkpython2.com/code/Time1.py). Solutions to the exercises are at [Here](http://thinkpython2.com/code/Time1_soln.py).
13 | >本章的样例代码可以在[这里](http://thinkpython2.com/code/Time1.py)下载。然后练习题的样例代码可以在[这里](http://thinkpython2.com/code/Time1_soln.py)下载到。
14 |
15 |
16 |
17 |
18 | ##16.1 Time 时间
19 |
20 |
21 | As another example of a programmer-defined type, we’ll define a class called Time that records the time of day. The class definition looks like this:
22 | >下面又是一个自定义类型的例子,这次咱们定义一个叫做 Time 的类,记录下当日的时间。
23 | >类的定义是如下这样:
24 |
25 | ```Python
26 | class Time:
27 | """Represents the time of day.
28 | attributes: hour, minute, second """
29 | ```
30 |
31 | We can create a new Time object and assign attributes for hours, minutes, and seconds:
32 | >我们可以建立一个新的 Time 对象,然后对时分秒分别进行赋值:
33 |
34 | ```Python
35 | time = Time()
36 | time.hour = 11
37 | time.minute = 59
38 | time.second = 30
39 | ```
40 |
41 |
42 | The state diagram for the Time object looks like Figure 16.1.
43 | >这个 Time 对象的状态图如图16.1所示。
44 |
45 |
46 | As an exercise, write a function called print_time that takes a Time object and prints it in the form hour:minute:second. Hint: the format sequence '%.2d' prints an integer using at least two digits, including a leading zero if necessary.
47 | >下面做个练习,写一个名为print_time 的函数,接收一个 Time 对象,然后以时:分:秒的格式来输出。提示:格式序列'%.2d'就会用两位来输出一个整数,第一位可以为0。
48 |
49 |
50 | Write a boolean function called is_after that takes two Time objects, t1 andt2, and returns True if t1 follows t2 chronologically and False otherwise. Challenge: don’t use an if statement.
51 | >写一个布尔函数,名为 is_after,接收两个 Time 对象,分别为 t1和 t2,然后如果 t1在时间上位于 t2的后面,就返回真,否则返回假。难度提高一下:不要用 if 语句,看你能搞定不。
52 |
53 |
54 | ________________________________________
55 | 
56 | Figure 16.1: Object diagram.
57 | ________________________________________
58 |
59 |
60 |
61 |
62 |
63 | ##16.2 Pure functions 纯函数
64 |
65 |
66 | In the next few sections, we’ll write two functions that add time values. They demonstrate two kinds of functions: pure functions and modifiers. They also demonstrate a development plan I’ll call prototype and patch, which is a way of tackling a complex problem by starting with a simple prototype and incrementally dealing with the complications.
67 | >后面的这些章节中,我们要写两个函数来对 time 进行加法操作。这两个函数展示了两种函数类型:纯函数和修改器。写这两个函数的过程中,也体现了我即将讲到的一种新的开发模式:原型和补丁模式,这种方法就是在处理复杂问题的时候,先从简单的原型开始,然后逐渐解决复杂的内容。
68 |
69 |
70 | Here is a simple prototype of add_time:
71 | >下面这段代码就是 add_time 函数的一个原型:
72 |
73 |
74 | ```Python
75 | def add_time(t1, t2):
76 | sum = Time()
77 | sum.hour = t1.hour + t2.hour
78 | sum.minute = t1.minute + t2.minute
79 | sum.second = t1.second + t2.second
80 | return sum
81 | ```
82 |
83 |
84 |
85 | The function creates a new Time object, initializes its attributes, and returns a reference to the new object. This is called a pure function because it does not modify any of the objects passed to it as arguments and it has no effect, like displaying a value or getting user input, other than returning a value.
86 | >这个函数新建了一个新的 Time 对象,初始化了所有的值,然后返回了一个对新对象的引用。这种函数叫纯函数,因为这种函数并不修改传来做参数的对象,也没有什么效果,比如显示值啊或者让用户输入啊等等,而只是返回一个值而已。
87 |
88 |
89 | To test this function, I’ll create two Time objects: start contains the start time of a movie, like Monty Python and the Holy Grail, and duration contains the run time of the movie, which is one hour 35 minutes. add_time figures out when the movie will be done.
90 | >下面就来测试一下这个函数,我将建立两个 Time 对象,start 包含了一个电影的开始时间,比如《巨蟒与圣杯》(译者注:1975年喜剧电影。Python的创造者Guido van Rossum特别喜欢这个喜剧团体:巨蟒飞行马戏团(Monty Python’s Flying Circus ),所以命名为 Python。),然后 duration(汉译就是持续时间)包含了该电影的时长,《巨蟒与圣杯》这部电影是一小时三十五分钟。add_time 函数就会算出电影结束的时间。
91 |
92 |
93 |
94 | ```Python
95 | >>> start = Time()
96 | >>> start.hour = 9
97 | >>> start.minute = 45
98 | >>> start.second = 0
99 | >>> duration = Time()
100 | >>> duration.hour = 1
101 | >>> duration.minute = 35
102 | >>> duration.second = 0
103 | >>> done = add_time(start, duration)
104 | >>> print_time(done)
105 | 10:80:00
106 | ```
107 |
108 |
109 |
110 |
111 | The result, 10:80:00 might not be what you were hoping for. The problem is that this function does not deal with cases where the number of seconds or minutes adds up to more than sixty. When that happens, we have to “carry” the extra seconds into the minute column or the extra minutes into the hour column.
112 | Here’s an improved version:
113 | >很明显,10点80分00秒这样的时间肯定不是你想要的结果。问题就出在了函数不值得如何应对时分秒的六十位进位,所以超过60的时候没进位就这样了。所以我们得把超出六十秒的进位到分,超过六十分的进位到小时。
114 | >下面这个是改进版本:
115 |
116 |
117 | ```Python
118 | def add_time(t1, t2):
119 | sum = Time()
120 | sum.hour = t1.hour + t2.hour
121 | sum.minute = t1.minute + t2.minute
122 | sum.second = t1.second + t2.second
123 | if sum.second >= 60:
124 | sum.second -= 60
125 | sum.minute += 1
126 | if sum.minute >= 60:
127 | sum.minute -= 60
128 | sum.hour += 1
129 | return sum
130 | ```
131 |
132 |
133 |
134 | Although this function is correct, it is starting to get big. We will see a shorter alternative later.
135 | >这回函数正确工作了,但代码也开始变多了。稍后我们就能看到一个短一些的替代方案。
136 |
137 |
138 | 16.3 Modifiers 修改器
139 |
140 |
141 |
142 | Sometimes it is useful for a function to modify the objects it gets as parameters. In that case, the changes are visible to the caller. Functions that work this way are called modifiers.
143 | >有时候需要对作为参数的对象进行一些修改。这时候这些修改就可以被调用者察觉。这样工作的函数就叫修改器了。
144 |
145 | increment, which adds a given number of seconds to a Time object, can be written naturally as a modifier. Here is a rough draft:
146 | >increment 函数,增加给定的秒数到一个 Time 对象,就可以被改写成一个修改器。
147 | >下面是个简单的版本:
148 |
149 |
150 | ```Python
151 | def increment(time, seconds):
152 | time.second += seconds
153 | if time.second >= 60:
154 | time.second -= 60
155 | time.minute += 1
156 | if time.minute >= 60:
157 | time.minute -= 60
158 | time.hour += 1
159 | ```
160 |
161 |
162 |
163 | The first line performs the basic operation; the remainder deals with the special cases we saw before.
164 | Is this function correct? What happens if seconds is much greater than sixty?
165 | >第一行代码进行了最简单的运算;后面的代码是用来应对我们之前讨论过的特例情况。
166 | >那么这个函数正确么?秒数超过六十会怎么样?
167 |
168 |
169 | In that case, it is not enough to carry once; we have to keep doing it until time.second is less than sixty. One solution is to replace the if statements with while statements. That would make the function correct, but not very efficient.
170 | >很明显,秒数超过六十的时候,就需要运行不只一次了;必须一直运行,之道 time.second 的值小于六十了才行。有一种办法就是把 if 语句换成 while 语句。这样就可以解决这个问题了,但效率不太高。
171 |
172 |
173 |
174 |
175 | As an exercise, write a correct version of increment that doesn’t contain any loops.
176 | >做个练习,写一个正确的 increment 函数,并且要不包含任何循环。
177 |
178 |
179 | Anything that can be done with modifiers can also be done with pure functions. In fact, some programming languages only allow pure functions. There is some evidence that programs that use pure functions are faster to develop and less error-prone than programs that use modifiers. But modifiers are convenient at times, and functional programs tend to be less efficient.
180 | >能用修改器实现的功能也都能用纯函数来实现。实际上有的编程语言只允许纯函数。有证据表明,与修改器相比,使用修改器能够更快地开发,而且不容易出错误。但修改器往往很方便好用,而函数式的程序一般效率要差一些。
181 |
182 |
183 |
184 | In general, I recommend that you write pure functions whenever it is reasonable and resort to modifiers only if there is a compelling advantage. This approach might be called a functional programming style.
185 | >总的来说,我还是建议你写纯函数,除非用修改器有特别显著的好处。这种模式也叫做函数式编程。
186 |
187 |
188 |
189 | As an exercise, write a “pure” version of increment that creates and returns a new Time object rather than modifying the parameter.
190 | >做个练习,写一个用纯函数实现的 increment,创建并返回一个新的 Time 对象,而不是修改参数。
191 |
192 |
193 | ##16.4 Prototyping versus planning 原型与规划
194 |
195 |
196 |
197 |
198 | The development plan I am demonstrating is called “prototype and patch”. For each function, I wrote a prototype that performed the basic calculation and then tested it, patching errors along the way.
199 | >这次我演示的开发规划就是『原型与补丁模式』。对每个函数,我都先谢了一个简单的原型,只进行基本的运算,然后测试一下,接下来逐步修补错误。
200 |
201 |
202 | This approach can be effective, especially if you don’t yet have a deep understanding of the problem. But incremental corrections can generate code that is unnecessarily complicated—since it deals with many special cases—and unreliable—since it is hard to know if you have found all the errors.
203 | >这种模式很有效率,尤其是在你对问题的理解不是很深入的时候。不过渐进式的修改也会产生过分复杂的代码——因为要应对很多特例情况,而且也不太靠靠——因为不好确定你是否找到了所有的错误。
204 |
205 |
206 |
207 |
208 | An alternative is designed development, in which high-level insight into the problem can make the programming much easier. In this case, the insight is that a Time object is really a three-digit number in base 60 (see [Here](http://en.wikipedia.org/wiki/Sexagesimal))! The second attribute is the “ones column”, the minute attribute is the “sixties column”, and the hour attribute is the “thirty-six hundreds column”.
209 | >另一种模式就是设计规划开发,这种情况下对问题的深入透彻的理解就让开发容易很多了。本节中的根本性认识就在于 TIme 对象实际上是一个三位的六十进制数字(参考 [这里的解释](http://en.wikipedia.org/wiki/Sexagesimal)。)!秒数也就是个位,分数也就是六十位,小时数就是三千六百位。
210 |
211 |
212 | When we wrote add_time and increment, we were effectively doing addition in base 60, which is why we had to carry from one column to the next.
213 | >这样当我们写 add_time 和 increment 函数的时候,用60进制来进行计算就很有效率。
214 |
215 |
216 |
217 | This observation suggests another approach to the whole problem—we can convert Time objects to integers and take advantage of the fact that the computer knows how to do integer arithmetic.
218 | >这一观察表明有另外一种方法来解决整个问题——我们可以把 Time 对象转换成整数,然后因为计算机最擅长整数运算,这样就有优势了。
219 |
220 |
221 | Here is a function that converts Times to integers:
222 | >下面这个函数就把 Times 转换成了整数:
223 |
224 |
225 | ```Python
226 | def time_to_int(time):
227 | minutes = time.hour * 60 + time.minute
228 | seconds = minutes * 60 + time.second
229 | return seconds
230 | ```
231 |
232 |
233 |
234 |
235 | And here is a function that converts an integer to a Time (recall that divmod divides the first argument by the second and returns the quotient and remainder as a tuple).
236 | >然后下面这个函数是反过来的,把整数转换成 Time(还记得 divmod 么,使用第一个数除以第二个数,返回的是除数和余数组成的元组。)
237 |
238 |
239 | ```Python
240 | def int_to_time(seconds):
241 | time = Time()
242 | minutes, time.second = divmod(seconds, 60)
243 | time.hour, time.minute = divmod(minutes, 60)
244 | return time
245 | ```
246 |
247 |
248 |
249 | You might have to think a bit, and run some tests, to convince yourself that these functions are correct. One way to test them is to check that time_to_int(int_to_time(x)) == x for many values of x. This is an example of a consistency check.
250 | >你最好先考虑好了,然后多进行几次测试运行,然后要确保这些函数都是正确的。比如你就可以试着用很多个 x 的值来运算time_to_int(int_to_time(x)) == x。这也是连贯性检测的一个例子。
251 |
252 |
253 |
254 | Once you are convinced they are correct, you can use them to rewrite add_time:
255 | >一旦你确定这些函数都没问题,就可以用它们来重写一下 add_time 这个函数了:
256 |
257 |
258 | ```Python
259 | def add_time(t1, t2):
260 | seconds = time_to_int(t1) + time_to_int(t2)
261 | return int_to_time(seconds)
262 | ```
263 |
264 |
265 |
266 | This version is shorter than the original, and easier to verify. As an exercise, rewrite increment using time_to_int and int_to_time.
267 | >这个版本就比最开始那个版本短多了,也更容易去检验了。接下来就做个联系吧,用time_to_int 和 int_to_time 这两个函数来重写一下 increment。
268 |
269 |
270 |
271 | In some ways, converting from base 60 to base 10 and back is harder than just dealing with times. Base conversion is more abstract; our intuition for dealing with time values is better.
272 | >在一定程度上,从六十进制到十进制的来回转换,远远比计算时间要麻烦的多。进制转换要更加抽象很多;我们处理时间计算的直觉要更好些。
273 |
274 |
275 |
276 | But if we have the insight to treat times as base 60 numbers and make the investment of writing the conversion functions (time_to_int and int_to_time), we get a program that is shorter, easier to read and debug, and more reliable.
277 | >然而,如果我们有足够的远见,把时间值当做六十进制的数值来对待,然后写出一些转换函数(比如 time_to_int 和 int_to_time),就能让程序变得更短,可读性更好,调试更容易,也更加可靠。
278 |
279 |
280 |
281 |
282 | It is also easier to add features later. For example, imagine subtracting two Times to find the duration between them. The naive approach would be to implement subtraction with borrowing. Using the conversion functions would be easier and more likely to be correct.
283 | >而且后续添加功能也更容易了。比如,假设要对两个时间对象进行相减来求二者之间的持续时间。简单版本的方法就是要用借位的减法。而使用转换函数的版本就更容易了,也更不容易出错。
284 |
285 |
286 |
287 |
288 | Ironically, sometimes making a problem harder (or more general) makes it easier (because there are fewer special cases and fewer opportunities for error).
289 | >有意思的事,有时候以困难模式来写一个程序(比如用更加泛化的模式),反而能让开发更简单(因为这样就减少了特例情况,也减少了出错误的概率了。)
290 |
291 |
292 |
293 |
294 | ##16.5 Debugging 调试
295 |
296 |
297 |
298 | A Time object is well-formed if the values of minute and second are between 0 and 60 (including 0 but not 60) and if hour is positive. hour and minute should be integral values, but we might allow second to have a fraction part.
299 | >对于一个 Time 对象来说,只要分和秒的值在0-60的前闭后开区间(即可以为0但不可以为60),并且小时数为正数,就是格式正确的。小时和分钟都应该是整数,但秒是可以为小数的。
300 |
301 |
302 |
303 |
304 | Requirements like these are called invariants because they should always be true. To put it a different way, if they are not true, something has gone wrong.
305 | >像这些要求也叫约束条件,因为通常都得满足这些条件才行。反过来说,如果这些条件没满足,就有可能是程序中某处存在错误了。
306 |
307 |
308 |
309 |
310 | Writing code to check invariants can help detect errors and find their causes. For example, you might have a function like valid_time that takes a Time object and returns False if it violates an invariant:
311 | >写一些检测约束条件的代码,能够帮助找出这些错误,并且找到导致错误的原因。例如,你亏写一个名字未 calid_time 的函数,接收一个 Time 对象,然后如果该对象不满足约束条件就返回 False:
312 |
313 |
314 |
315 | ```Python
316 | def valid_time(time):
317 | if time.hour < 0 or time.minute < 0 or time.second < 0:
318 | return False
319 | if time.minute >= 60 or time.second >= 60:
320 | return False
321 | return True
322 | ```
323 |
324 |
325 |
326 | At the beginning of each function you could check the arguments to make sure they are valid:
327 | >然后在每个自定义函数的开头部位,你就可以检测一下参数,来确保这些参数没有错误:
328 |
329 |
330 | ```Python
331 | def add_time(t1, t2):
332 | if not valid_time(t1) or not valid_time(t2):
333 | raise ValueError('invalid Time object in add_time')
334 | seconds = time_to_int(t1) + time_to_int(t2)
335 | return int_to_time(seconds)
336 | ```
337 |
338 |
339 |
340 |
341 | Or you could use an assert statement, which checks a given invariant and raises an exception if it fails:
342 | >或者你也可以用一个 assert 语句,这个语句也是检测给定的约束条件的,如果出现错误就会抛出一个异常:
343 |
344 |
345 | ```Python
346 | def add_time(t1, t2):
347 | assert valid_time(t1) and valid_time(t2)
348 | seconds = time_to_int(t1) + time_to_int(t2)
349 | return int_to_time(seconds)
350 | ```
351 |
352 |
353 |
354 | assert statements are useful because they distinguish code that deals with normal conditions from code that checks for errors.
355 | >assert 语句是很有用的,可以用来区分条件语句的用途,将 assert 这种用于检查错误的语句与常规的条件语句在代码上进行区分。
356 |
357 |
358 |
359 |
360 | ##16.6 Glossary 术语列表
361 |
362 |
363 |
364 |
365 | prototype and patch:
366 | A development plan that involves writing a rough draft of a program, testing, and correcting errors as they are found.
367 | >原型和补丁模式:一种开发模式,先写一个程序的草稿,然后测试,再改正发现的错误,这样逐步演化的开发模式。
368 |
369 |
370 |
371 |
372 |
373 | designed development:
374 | A development plan that involves high-level insight into the problem and more planning than incremental development or prototype development.
375 | >设计规划开发:这种开发模式要求对所面对问题的高程度的深刻理解,相比渐进式开发和原型增补模式要更具有计划性。
376 |
377 |
378 |
379 |
380 | pure function:
381 | A function that does not modify any of the objects it receives as arguments. Most pure functions are fruitful.
382 | >纯函数:不修改参数对象的函数。这种函数多数是有返回值的函数。
383 |
384 |
385 |
386 | modifier:
387 | A function that changes one or more of the objects it receives as arguments. Most modifiers are void; that is, they return None.
388 | >修改器:修改参数对象的函数。大多数这样的函数都是无返回值的,也就是返回的都是 None。
389 |
390 |
391 |
392 |
393 | functional programming style:
394 | A style of program design in which the majority of functions are pure.
395 | >函数式编程模式:一种程序设计模式,主要特征为大多数函数都是纯函数。
396 |
397 |
398 |
399 | invariant:
400 | A condition that should always be true during the execution of a program.
401 | >约束条件:在程序运行过程中,应该一直为真的条件。
402 |
403 |
404 |
405 | assert statement:
406 | A statement that check a condition and raises an exception if it fails.
407 | >assert 语句:一种检查错误的语句,检查一个条件,如果不满足就抛出异常。
408 |
409 |
410 |
411 |
412 | ##16.7 Exercises 练习
413 |
414 |
415 |
416 | Code examples from this chapter are available from [Here](http://thinkpython2.com/code/Time1.py); solutions to the exercises are available from [Here](http://thinkpython2.com/code/Time1_soln.py).
417 | >本章的例子可以在 [这里](http://thinkpython2.com/code/Time1.py)下载;练习题的答案可以在[这里](http://thinkpython2.com/code/Time1_soln.py)下载。
418 |
419 |
420 |
421 | ###Exercise 1 练习1
422 |
423 |
424 |
425 |
426 | Write a function called mul_time that takes a Time object and a number and returns a new Time object that contains the product of the original Time and the number.
427 | >写一个函数,名为mul_time,接收一个Time 对象和一个数值,返回一个二者相乘得到的新的Time 对象。
428 |
429 |
430 | Then use mul_time to write a function that takes a Time object that represents the finishing time in a race, and a number that represents the distance, and returns a Time object that represents the average pace (time per mile).
431 | >然后用 mul_time 这个函数写一个函数,接收一个 Time 对象,代表着一个比赛的结束时间,还有一个数值,代表比赛距离,然后返回一个表示了平均步调(单位距离花费的时间)的新的 Time 对象。
432 |
433 |
434 |
435 | ###Exercise 2 练习2
436 |
437 |
438 | The datetime module provides time objects that are similar to the Time objects in this chapter, but they provide a rich set of methods and operators. Read the documentation at [Here](http://docs.python.org/3/library/datetime.html).
439 | >datetime 模块提供了一些 time 对象,和本章的 Time 对象很相似,但前者提供了更多的方法和运算符。读一读[这里的文档] [Here](http://docs.python.org/3/library/datetime.html)吧。
440 |
441 |
442 |
443 |
444 | 1. Use the datetime module to write a program that gets the current date and prints the day of the week.
445 | >用 datetime 模块来写一个函数,获取当前日期,然后输出今天是星期几。
446 |
447 |
448 |
449 |
450 | 2. Write a program that takes a birthday as input and prints the user’s age and the number of days, hours, minutes and seconds until their next birthday.
451 | >写一个函数,要求输入生日,然后输出用户的年龄以及距离下一个生日的日、时、分、秒数。
452 |
453 |
454 |
455 |
456 | 3. For two people born on different days, there is a day when one is twice as old as the other. That’s their Double Day. Write a program that takes two birthdays and computes their Double Day.
457 | >有的两个人在不同日期出生,会在某一天,一个人的年龄是另外一个人年龄的两杯。这一天就叫做他们的双倍日。写一个函数,接收两个生日,然后计算双倍日。
458 |
459 |
460 |
461 |
462 | 4. For a little more challenge, write the more general version that computes the day when one person is n times older than the other.
463 | >再来点有挑战性的,写一个更通用的版本,来计算一下一个人的年龄为另外一个人年龄 n 倍时候的日期。
464 |
465 |
466 |
467 | [Solution](http://thinkpython2.com/code/double.py).
468 | >[样例代码](http://thinkpython2.com/code/double.py)。
469 |
470 |
--------------------------------------------------------------------------------
/ThinkPython-19.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 19
2 | Date: 2016-2-10
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 19 The Goodies 额外补充
7 |
8 |
9 |
10 |
11 | One of my goals for this book has been to teach you as little Python as possible. When there were two ways to do something, I picked one and avoided mentioning the other. Or sometimes I put the second one into an exercise.
12 | >我在本书中的一个目标就是尽量少教你 Python(译者注:而要多教编程)。有的时候完成一个目的有两种方法,我都会只选择一种而不提其他的。或者有的时候我就把第二个方法放到练习里面。
13 |
14 |
15 |
16 | Now I want to go back for some of the good bits that got left behind. Python provides a number of features that are not really necessary—you can write good code without them—but with them you can sometimes write code that’s more concise, readable or efficient, and sometimes all three.
17 | >现在我就要往回倒车一下,捡起一些当时略过的重要内容来给大家讲一下。Python 提供了很多并非必须的功能—你完全可以不用这些功能也能写出很好的代码—但用这些功能有时候能让你的代码更加简洁,可读性更强,或者更有效率,甚至有时候能兼顾这三个方面。
18 |
19 |
20 |
21 |
22 | ##19.1 Conditional expressions 条件表达式
23 |
24 |
25 |
26 | We saw conditional statements in Section 5.4. Conditional statements are often used to choose one of two values; for example:
27 | >在5.4中,我们见到了条件语句。条件语句往往用于二选一的情况下;比如:
28 |
29 |
30 | ```Python
31 | if x > 0:
32 | y = math.log(x)
33 | else:
34 | y = float('nan')
35 | ```
36 |
37 |
38 |
39 | This statement checks whether x is positive. If so, it computes math.log. If not,math.log would raise a ValueError. To avoid stopping the program, we generate a “NaN”, which is a special floating-point value that represents “Not a Number”.
40 | >这个语句检查了 x 是否为正数。如果为正数,程序就计算对数值 math.log。如果非正,对数函数会返回一个值错误 ValueError。要避免因此而导致程序异常退出,咱们就生成了一个『NaN』,这个符号是一个特别的浮点数的值,表示的意思是『不是一个数』。
41 |
42 |
43 |
44 | We can write this statement more concisely using a conditional expression:
45 | >用一个条件表达式能让这个语句更简洁:
46 |
47 |
48 | ```Python
49 | y = math.log(x) if x > 0 else float('nan')
50 | ```
51 |
52 |
53 |
54 | You can almost read this line like English: “y gets log-x if x is greater than 0; otherwise it gets NaN”.
55 | Recursive functions can sometimes be rewritten using conditional expressions. For example, here is a recursive version of factorial:
56 | >上面这行代码读起来就跟英语一样了:『如果 x 大于0就让 y 等于 x 的对数;否则的话就返回 Nan』。
57 | >递归函数有时候也可以用这种条件表达式来改写。例如下面就是分形函数 factorial 的一个递归版本:
58 |
59 |
60 |
61 | ```Python
62 | def factorial(n):
63 | if n == 0:
64 | return 1
65 | else:
66 | return n * factorial(n-1)
67 | ```
68 |
69 |
70 |
71 |
72 | We can rewrite it like this:
73 | >我们可以这样改写:
74 |
75 |
76 |
77 | ```Python
78 | def factorial(n):
79 | return 1 if n == 0 else return n * factorial(n-1)
80 | ```
81 |
82 |
83 | Another use of conditional expressions is handling optional arguments. For example, here is the init method from GoodKangaroo (see Exercise 2):
84 | >条件表达式还可以用于处理可选参数。例如下面就是练习2中 GoodKangaroo 类的 init 方法:
85 |
86 |
87 | ```Python
88 | def __init__(self, name, contents=None):
89 | self.name = name
90 | if contents == None:
91 | contents = []
92 | self.pouch_contents = contents
93 | ```
94 |
95 |
96 |
97 |
98 | We can rewrite this one like this:
99 | >我们可以这样来改写:
100 |
101 |
102 | ```Python
103 | def __init__(self, name, contents=None):
104 | self.name = name
105 | self.pouch_contents = []
106 | if contents == None else contents
107 | ```
108 |
109 |
110 |
111 |
112 |
113 | In general, you can replace a conditional statement with a conditional expression if both branches contain simple expressions that are either returned or assigned to the same variable.
114 | >一般来讲,你可以用条件表达式来替换掉条件语句,无论这些语句的分支是返回语句或者是赋值语句。
115 |
116 |
117 |
118 |
119 | ##19.2 List comprehensions 列表推导
120 |
121 |
122 |
123 |
124 | In Section 10.7 we saw the map and filter patterns. For example, this function takes a list of strings, maps the string method capitalize to the elements, and returns a new list of strings:
125 | >在10.7当中,我们看到了映射和过滤模式。例如,下面这个函数接收一个字符串列表,然后将每一个元素都用字符串方法 capitalize 处理成大写的,然后返回一个新的字符串列表:
126 |
127 |
128 | ```Python
129 | def capitalize_all(t):
130 | res = []
131 | for s in t:
132 | res.append(s.capitalize())
133 | return res
134 | ```
135 |
136 |
137 |
138 |
139 | We can write this more concisely using a list comprehension:
140 | >用列表推导就可以将上面的代码写得更简洁:
141 |
142 |
143 | ```Python
144 | def capitalize_all(t):
145 | return [s.capitalize() for s in t]
146 | ```
147 |
148 |
149 |
150 | The bracket operators indicate that we are constructing a new list. The expression inside the brackets specifies the elements of the list, and the for clause indicates what sequence we are traversing.
151 | >方括号的意思是我们正在建立一个新的列表。方括号内的表达式确定了此新列表中的元素,然后 for 语句表明我们要遍历的序列。
152 |
153 |
154 |
155 | The syntax of a list comprehension is a little awkward because the loop variable, s in this example, appears in the expression before we get to the definition.
156 | >列表推导的语法有点复杂,就因为这个循环变量,在上面例子中是 s,这个 s 在我们定义之前就出现在语句中了。
157 |
158 |
159 |
160 | List comprehensions can also be used for filtering. For example, this function selects only the elements of t that are upper case, and returns a new list:
161 | >列表推导也可以用到滤波中。例如,下面的函数从 t 中选择了大写的元素,然后返回成一个新的列表:
162 |
163 |
164 | ```Python
165 | def only_upper(t):
166 | res = []
167 | for s in t:
168 | if s.isupper():
169 | res.append(s)
170 | return res
171 | ```
172 |
173 |
174 |
175 |
176 |
177 | We can rewrite it using a list comprehension:
178 | >咱们可以用列表推导来重写这个函数:
179 |
180 |
181 | ```Python
182 | def only_upper(t):
183 | return [s for s in t if s.isupper()]
184 | ```
185 |
186 |
187 |
188 |
189 |
190 | List comprehensions are concise and easy to read, at least for simple expressions. And they are usually faster than the equivalent for loops, sometimes much faster. So if you are mad at me for not mentioning them earlier, I understand.
191 | >列表推导很简洁,也很容易阅读,至少在简单的表达式上是这样。这些语句的执行也往往比同样情况下的 for 循环更快一些,有时候甚至快很多。所以如果你因为我没有早些给你讲而发怒,我也能理解。
192 |
193 |
194 |
195 |
196 | But, in my defense, list comprehensions are harder to debug because you can’t put a print statement inside the loop. I suggest that you use them only if the computation is simple enough that you are likely to get it right the first time. And for beginners that means never.
197 | >但是,我也要辩护一下,列表推导会导致调试非常困难,因为你不能在循环内部放 print 语句了。我建议你只去在一些简单的地方使用,要确保你第一次写出来就能保证代码正常工作。也就是说初学者就还是别用为好。
198 |
199 |
200 |
201 |
202 |
203 | ##19.3 Generator expressions 生成器表达式
204 |
205 |
206 |
207 | Generator expressions are similar to list comprehensions, but with parentheses instead of square brackets:
208 | >生成器表达式与列表推导相似,用的不是方括号,而是圆括号:
209 |
210 | ```Python
211 | >>> g = (x**2 for x in range(5))
212 | >>> g
213 | at 0x7f4c45a786c0>
214 | ```
215 |
216 |
217 |
218 | The result is a generator object that knows how to iterate through a sequence of values. But unlike a list comprehension, it does not compute the values all at once; it waits to be asked. The built-in function next gets the next value from the generator:
219 | >上面这样运行得到的结果就是一个生成器对象,用来遍历一个值的序列。但与列表推导不同的是,生成器表达式并不会立即计算出所有的值;它要等着被调用。内置函数 next 会从生成器中得到下一个值:
220 |
221 |
222 | ```Python
223 | >>> next(g)
224 | 0
225 | >>> next(g)
226 | 1
227 | ```
228 |
229 | When you get to the end of the sequence, next raises a StopIteration exception. You can also use a for loop to iterate through the values:
230 | >当程序运行到序列末尾的时候,next 函数就会抛出一个停止遍历的异常。你也可以用一个 for 循环来遍历所有的值:
231 |
232 |
233 | ```Python
234 | >>> for val in g: ...
235 | print(val)
236 | 4
237 | 9
238 | 16
239 | ```
240 |
241 |
242 |
243 |
244 |
245 |
246 | The generator object keeps track of where it is in the sequence, so the for loop picks up where next left off. Once the generator is exhausted, it continues to raise StopException:
247 | >生成器对象能够追踪在序列中的位置,所以 for 语句就会在 next 函数退出的地方开始。一旦生成器使用完毕了,接下来就要抛出一个停止异常了:
248 |
249 |
250 |
251 | ```Python
252 | >>> next(g)
253 | StopIteration
254 | ```
255 |
256 |
257 |
258 |
259 | Generator expressions are often used with functions like sum, max, and min:
260 | >生成器表达式多用于求和、求最大或者最小这样的函数中:
261 |
262 |
263 |
264 | ```Python
265 | >>> sum(x**2 for x in range(5))
266 | 30
267 | ```
268 |
269 |
270 |
271 | ##19.4 any and all 任意和所有
272 |
273 |
274 |
275 | Python provides a built-in function, any, that takes a sequence of boolean values and returns True if any of the values are True. It works on lists:
276 | >Python 提供了一个名为 any 的内置函数,该函数接收一个布尔值序列,只要里面有任意一个是真,就返回真。该函数适用于列表:
277 |
278 |
279 |
280 | ```Python
281 | >>> any([False, False, True])
282 | True
283 | ```
284 |
285 |
286 |
287 |
288 |
289 | But it is often used with generator expressions:
290 | >但这个函数多用于生成器表达式中:
291 |
292 |
293 |
294 |
295 | ```Python
296 | >>> any(letter == 't' for letter in 'monty')
297 | True
298 | ```
299 |
300 |
301 |
302 |
303 |
304 | That example isn’t very useful because it does the same thing as the in operator. But we could use any to rewrite some of the search functions we wrote in Section 9.3. For example, we could write avoids like this:
305 | >这个例子没多大用,因为效果和 in 运算符是一样的。但我们能用 any 函数来改写我们在9.3中写的一些搜索函数。例如,我们可以用如下的方式来改写 avoids:
306 |
307 |
308 |
309 |
310 | ```Python
311 | def avoids(word, forbidden):
312 | return not any(letter in forbidden for letter in word)
313 | ```
314 |
315 |
316 |
317 | The function almost reads like English, “word avoids forbidden if there are not any forbidden letters in word.”
318 | >这样这个函数读起来基本就跟英语一样了。
319 |
320 | Using any with a generator expression is efficient because it stops immediately if it finds a True value, so it doesn’t have to evaluate the whole sequence.
321 | >用 any 函数和生成器表达式来配合会很有效率,因为只要发现真值程序就会停止了,所以并不需要对整个序列进行运算。
322 |
323 |
324 |
325 | Python provides another built-in function, all, that returns True if every element of the sequence is True. As an exercise, use all to re-write uses_all from Section 9.3.
326 | >Python 还提供了另外一个内置函数 all,该函数在整个序列都是真的情况下才返回真。
327 | >做个练习,用 all 来改写一下9.3中的uses_all 函数。
328 |
329 |
330 |
331 |
332 | ##19.5 Sets 集合
333 |
334 |
335 |
336 |
337 | In Section 13.6 I use dictionaries to find the words that appear in a document but not in a word list. The function I wrote takes d1, which contains the words from the document as keys, and d2, which contains the list of words. It returns a dictionary that contains the keys from d1 that are not in d2.
338 | >在13.6中,我用了字典来查找存在于文档中而不存在于词汇列表中的词汇。我写的这个函数接收两个参数,一个是 d1是包含了文档中的词作为键,另外一个是 d2包含了词汇列表。程序会返回一个字典,这个字典包含的键存在于 d1而不在 d2中。
339 |
340 |
341 |
342 | ```Python
343 | def subtract(d1, d2):
344 | res = dict()
345 | for key in d1:
346 | if key not in d2:
347 | res[key] = None
348 | return res
349 | ```
350 |
351 |
352 |
353 |
354 |
355 |
356 | In all of these dictionaries, the values are None because we never use them. As a result, we waste some storage space.
357 | >在这些字典中,键值都是 None,因为根本没有使用。结果就是,浪费了一些存储空间。
358 |
359 |
360 | Python provides another built-in type, called a set, that behaves like a collection of dictionary keys with no values. Adding elements to a set is fast; so is checking membership. And sets provide methods and operators to compute common set operations.
361 | >Python 还提供了另一个内置类型,名为 set(也就是集合的意思),其性质就是有字典的键而无键值。
362 | >对集合中添加元素是很快的;对集合成员进行检查也很快。此外集合还提供了一些方法和运算符来进行常见的集合运算。
363 |
364 |
365 |
366 | For example, set subtraction is available as a method called difference or as an operator, -. So we can rewrite subtract like this:
367 | >例如,集合的减法就可以用一个名为 difference 的方法,或者就用减号-。所以我们可以把 subtract 改写成如下形式:
368 |
369 |
370 |
371 |
372 | ```Python
373 | def subtract(d1, d2):
374 | return set(d1) - set(d2)
375 | ```
376 |
377 |
378 |
379 |
380 |
381 |
382 | The result is a set instead of a dictionary, but for operations like iteration, the behavior is the same.
383 | >上面这个函数的结果就是一个集合而不是一个字典,但对于遍历等等运算来说,用起来都一样的。
384 |
385 |
386 |
387 |
388 | Some of the exercises in this book can be done concisely and efficiently with sets. For example, here is a solution to has_duplicates, from Exercise 7, that uses a dictionary:
389 | >本书中的一些练习都可以通过使用集合而改写成更精简更高效的形式。例如,下面的代码就是 has_duplicates 的一个实现方案,来自练习7,用的是字典:
390 |
391 |
392 |
393 |
394 |
395 |
396 | ```Python
397 | def has_duplicates(t):
398 | d = {}
399 | for x in t:
400 | if x in d:
401 | return True
402 | d[x] = True
403 | return False
404 | ```
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 | When an element appears for the first time, it is added to the dictionary. If the same element appears again, the function returns True.
416 | >当一个元素第一次出现的时候,就被添加到字典中。如果同一个元素又出现了,该函数就返回真。
417 |
418 |
419 |
420 | Using sets, we can write the same function like this:
421 | >用集合的话,我们就能把该函数写成如下形式:
422 |
423 |
424 |
425 |
426 | ```Python
427 | def has_duplicates(t):
428 | return len(set(t)) < len(t)
429 | ```
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 | An element can only appear in a set once, so if an element in t appears more than once, the set will be smaller than t. If there are no duplicates, the set will be the same size as t.
438 | >一个元素在一个集合中只能出现一次,所以如果一个元素在 t 中出现次数超过一次,集合会比 t 规模小一些。如果没有重复,集合的规模就应该和 t 一样大。
439 |
440 |
441 |
442 | We can also use sets to do some of the exercises in Chapter 9. For example, here’s a version of uses_only with a loop:
443 | >我们还能用集合来做一些第九章的练习。例如,下面就是用一个循环实现的一个版本的 uses_only:
444 |
445 |
446 |
447 | ```Python
448 | def uses_only(word, available):
449 | for letter in word:
450 | if letter not in available:
451 | return False
452 | return True
453 | ```
454 |
455 |
456 |
457 |
458 |
459 | uses_only checks whether all letters in word are in available. We can rewrite it like this:
460 | >uses_only 会检查 word 中的所有字母是否出现在 available 中。我们可以用如下方法重写:
461 |
462 |
463 |
464 | ```Python
465 | def uses_only(word, available):
466 | return set(word) <= set(available)
467 | ```
468 |
469 |
470 |
471 |
472 | The <= operator checks whether one set is a subset or another, including the possibility that they are equal, which is true if all the letters in word appear in available.
473 | As an exercise, rewrite avoids using sets.
474 | >这里的<=运算符会检查一个集合是否切另外一个集合的子集或者相等,如果 word 中所有的字符都出现在 available 中就返回真。
475 |
476 |
477 |
478 |
479 | ##19.6 Counters 计数器
480 |
481 |
482 |
483 |
484 | A Counter is like a set, except that if an element appears more than once, the Counter keeps track of how many times it appears. If you are familiar with the mathematical idea of a multiset, a Counter is a natural way to represent a multiset.
485 | >计数器跟集合相似,除了一点,就是如果计数器中元素出现的次数超过一次,计数器会记录下出现的次数。如果你对数学上多重集的概念有所了解,就会知道计数器是一种对多重集的表示方式。
486 |
487 |
488 |
489 | Counter is defined in a standard module called collections, so you have to import it. You can initialize a Counter with a string, list, or anything else that supports iteration:
490 | >计数器定义在一个名为 collections 的标准模块中,所以你必须先导入一下。你可以用字符串,列表或者任何支持遍历的类型来初始化一个计数器:
491 |
492 |
493 | ```Python
494 | >>> from collections import Counter
495 | >>> count = Counter('parrot')
496 | >>> count
497 | Counter({'r': 2, 't': 1, 'o': 1, 'p': 1, 'a': 1})
498 | ```
499 |
500 |
501 |
502 |
503 |
504 | Counters behave like dictionaries in many ways; they map from each key to the number of times it appears. As in dictionaries, the keys have to be hashable.
505 | >计数器的用法与字典在很多方面都相似;二者都映射了每个键到出现的次数上。在字典中,键必须是散列的。
506 |
507 |
508 | Unlike dictionaries, Counters don’t raise an exception if you access an element that doesn’t appear. Instead, they return 0:
509 | >与字典不同的是,当你读取一个不存在的元素的时候,计数器并不会抛出异常。相反的,这时候程序会返回0:
510 |
511 |
512 |
513 | ```Python
514 | >>> count['d']
515 | 0
516 | ```
517 |
518 |
519 |
520 |
521 | We can use Counters to rewrite is_anagram from Exercise 6:
522 | >我们可以用计数器来重写一下练习6中的这个 is_anagram 函数:
523 |
524 |
525 | ```Python
526 | def is_anagram(word1, word2):
527 | return Counter(word1) == Counter(word2)
528 | ```
529 |
530 |
531 |
532 | If two words are anagrams, they contain the same letters with the same counts, so their Counters are equivalent.
533 | Counters provide methods and operators to perform set-like operations, including addition, subtraction, union and intersection. And they provide an often-useful method, most_common, which returns a list of value-frequency pairs, sorted from most common to least:
534 | >如果两个单词是换位词,他们包含同样个数的同样字母,所以他们的计数器是相等的。
535 | >计数器提供了一些方法和运算器来运行类似集合的运算,包括加法,剪发,合并和交集等等。此外还提供了一个最常用的方法,most_common,该方法会返回一个由值-出现概率组成的数据对的列表,按照概率从高到低排列:
536 |
537 |
538 |
539 | ```Python
540 | >>> count = Counter('parrot')
541 | >>> for val, freq in count.most_common(3): ...
542 | print(val, freq)
543 | r 2
544 | p 1
545 | a 1
546 | ```
547 |
548 |
549 |
550 |
551 | ##19.7 defaultdict 默认字典
552 |
553 |
554 |
555 | The collections module also provides defaultdict, which is like a dictionary except that if you access a key that doesn’t exist, it can generate a new value on the fly.
556 | >collection 模块还提供了一个默认字典,与普通字典的区别在于当你读取一个不存在的键的时候,程序会添加上一个新值给这个键。
557 |
558 |
559 |
560 | When you create a defaultdict, you provide a function that’s used to create new values. A function used to create objects is sometimes called a factory. The built-in functions that create lists, sets, and other types can be used as factories:
561 | >当你创建一个默认字典的时候,就提供了一个能创建新值的函数。用来创建新对象的函数也被叫做工厂。内置的创建列表、集合以及其他类型的函数都可以被用作工厂:
562 |
563 |
564 | ```Python
565 | >>> from collections import defaultdict
566 | >>> d = defaultdict(list)
567 | ```
568 |
569 |
570 |
571 |
572 | Notice that the argument is list, which is a class object, not list(), which is a new list. The function you provide doesn’t get called unless you access a key that doesn’t exist.
573 | >要注意到这里的参数是一个列表,是一个类的对象,而不是 list(),带括号的就是一个新列表了。这个创建新值的函数只有当你试图读取一个不存在的键的时候才会被调用。
574 |
575 |
576 | ```Python
577 | >>> t = d['new key']
578 | >>> t []
579 | ```
580 |
581 | The new list, which we’re calling t, is also added to the dictionary. So if we modify t, the change appears in d:
582 | >新的这个我们称之为 t 的列表,也会被添加到字典中。所以如果我们修改 t,这种修改也会在 d 中出现。
583 |
584 |
585 |
586 |
587 | ```Python
588 | >>> t.append('new value')
589 | >>> d
590 | defaultdict(, {'new key': ['new value']})
591 | ```
592 |
593 |
594 |
595 |
596 | If you are making a dictionary of lists, you can often write simpler code using defaultdict. In my solution to Exercise 2, which you can get from [Here](http://thinkpython2.com/code/anagram_sets.py), I make a dictionary that maps from a sorted string of letters to the list of words that can be spelled with those letters. For example, ’opst’ maps to the list [’opts’, ’post’, ’pots’, ’spot’, ’stop’, ’tops’].
597 | >所以如果你要用列表组成字典的话,你就可以多用默认字典来写出更简洁的代码。你可以在[这里](http://thinkpython2.com/code/anagram_sets.py)下载我给练习2提供的样例代码,其中我建立了一个字典,字典中建立了从一个字母字符串到一个可以由这些字母拼成的单词的映射。例如,『opst』就映射到了列表[’opts’, ’post’, ’pots’, ’spot’, ’stop’, ’tops’]。
598 |
599 |
600 |
601 | Here’s the original code:
602 | >下面就是原版的代码:
603 |
604 | ```Python
605 | def all_anagrams(filename):
606 | d = {}
607 | for line in open(filename):
608 | word = line.strip().lower()
609 | t = signature(word)
610 | if t not in d:
611 | d[t] = [word]
612 | else:
613 | d[t].append(word)
614 | return d
615 | ```
616 |
617 |
618 |
619 |
620 |
621 |
622 | This can be simplified using setdefault, which you might have used in Exercise 2:
623 | >用默认集合就可以简化一下,就如你在练习2中用过的那样:
624 |
625 |
626 | ```Python
627 | def all_anagrams(filename):
628 | d = {}
629 | for line in open(filename):
630 | word = line.strip().lower()
631 | t = signature(word)
632 | d.setdefault(t, []).append(word)
633 | return d
634 | ```
635 |
636 |
637 |
638 |
639 |
640 | This solution has the drawback that it makes a new list every time, regardless of whether it is needed. For lists, that’s no big deal, but if the factory function is complicated, it might be.
641 | >这个代码有一个不足,就是每次都要建立一个新列表,而不论是否需要创建。对于列表来说,这倒不要紧,不过如果工厂函数比较复杂的话,这就麻烦了。
642 |
643 |
644 |
645 | We can avoid this problem and simplify the code using a defaultdict:
646 | >这时候咱们就可以用默认字典来避免这个问题并且简化代码:
647 |
648 |
649 | ```Python
650 | def all_anagrams(filename):
651 | d = defaultdict(list)
652 | for line in open(filename):
653 | word = line.strip().lower()
654 | t = signature(word)
655 | d[t].append(word)
656 | return d
657 | ```
658 |
659 |
660 |
661 |
662 | My solution to Exercise 3, which you can download from [Here](http://thinkpython2.com/code/PokerHandSoln.py), uses setdefault in the function has_straightflush. This solution has the drawback of creating a Hand object every time through the loop, whether it is needed or not. As an exercise, rewrite it using a defaultdict.
663 | >你可以从[这里](http://thinkpython2.com/code/PokerHandSoln.py)下载我给练习3写的样例代码,该代码中在 has_straightflush函数用的是默认集合。这份代码的不足就在于每次循环都要创建一个 Hand 对象,而不论是否必要。做个练习,用默认字典来该写一下这个程序。
664 |
665 |
666 |
667 | ##19.8 Named tuples 命名元组
668 |
669 |
670 |
671 | Many simple objects are basically collections of related values. For example, the Point object defined in Chapter 15 contains two numbers, x and y. When you define a class like this, you usually start with an init method and a str method:
672 | >很多简单的类就是一些相关值的集合。例如在15章中定义的 Point 类中就包含两个数值,x 和 y。当你这样定义一个类的时候,你通常要写一个 init 方法和一个 str 方法:
673 |
674 |
675 | ```Python
676 | class Point:
677 | def __init__(self, x=0, y=0):
678 | self.x = x
679 | self.y = y
680 |
681 | def __str__(self):
682 | return '(%g, %g)' % (self.x, self.y)
683 | ```
684 |
685 |
686 |
687 |
688 |
689 | This is a lot of code to convey a small amount of information. Python provides a more concise way to say the same thing:
690 | >要传达这么小规模的信息却要用这么多代码。Python 提供了一个更简单的方式来做类似的事情:
691 |
692 |
693 |
694 | ```Python
695 | from collections import namedtuple
696 | Point = namedtuple('Point', ['x', 'y'])
697 | ```
698 |
699 |
700 |
701 |
702 |
703 | The first argument is the name of the class you want to create. The second is a list of the attributes Point objects should have, as strings. The return value from named tuple is a class object:
704 | >第一个参数是你要写的类的名字。第二个是 Point 对象需要有的属性列表,为字符串。命名元组返回的值是一个类的对象。
705 |
706 |
707 |
708 | ```Python
709 | >>> Point
710 |
711 | ```
712 |
713 |
714 |
715 |
716 | Point automatically provides methods like __init__ and __str__ so you don’t have to write them.
717 | To create a Point object, you use the Point class as a function:
718 | >Point 会自动提供诸如 init 和 str 之类的方法,所以就不用再去写了。
719 | >要建立一个 Point 对象,你就可以用 Point 类作为一个函数用:
720 |
721 |
722 |
723 | ```Python
724 | >>> p = Point(1, 2)
725 | >>> p
726 | Point(x=1, y=2)
727 | ```
728 |
729 |
730 |
731 |
732 |
733 |
734 | The init method assigns the arguments to attributes using the names you provided. The str method prints a representation of the Point object and its attributes.
735 | You can access the elements of the named tuple by name:
736 | >init 方法把参数赋值给按照你设定来命名的属性。 str 方法输出整个 Point 类及其属性的一个字符串表达。
737 | >你可以用名字来读取命名元组中的元素:
738 |
739 |
740 |
741 | ```Python
742 | >>> p.x, p.y
743 | (1, 2)
744 | ```
745 |
746 |
747 |
748 |
749 | But you can also treat a named tuple as a tuple:
750 | >但你也可以把命名元组当做元组来用:
751 |
752 |
753 | ```Python
754 | >>> p[0], p[1]
755 | (1, 2)
756 | >>> x, y = p
757 | >>> x, y
758 | (1, 2)
759 | ```
760 |
761 |
762 |
763 |
764 |
765 |
766 | Named tuples provide a quick way to define simple classes. The drawback is that simple classes don’t always stay simple. You might decide later that you want to add methods to a named tuple. In that case, you could define a new class that inherits from the named tuple:
767 | >命名元组提供了定义简单类的快捷方式。缺点就是这些简单的类不能总保持简单的状态。有时候你可能想给一个命名元组添加方法。这时候你就得定义一个新类来继承命名元组:
768 |
769 |
770 | ```Python
771 | class Pointier(Point):
772 | # add more methods here
773 | ```
774 |
775 |
776 |
777 | Or you could switch to a conventional class definition.
778 | >或者你可以把命名元组转换成一个常规的类的定义。
779 |
780 |
781 |
782 | ##19.9 Gathering keyword args 收集关键词参数
783 |
784 |
785 |
786 | In Section 12.4, we saw how to write a function that gathers its arguments into a tuple:
787 | >在12.4中,我们已经学过了如何写将参数收集到一个元组中的函数:
788 |
789 | ```Python
790 | def printall(*args):
791 | print(args)
792 | ```
793 |
794 |
795 |
796 |
797 | You can call this function with any number of positional arguments (that is, arguments that don’t have keywords):
798 | >这种函数可以用任意数量的位置参数(就是无关键词的参数)来调用。
799 |
800 |
801 | ```Python
802 | >>> printall(1, 2.0, '3')
803 | (1, 2.0, '3')
804 | ```
805 |
806 |
807 |
808 |
809 |
810 | But the * operator doesn’t gather keyword arguments:
811 | >但*运算符并不能收集关键词参数:
812 |
813 |
814 | ```Python
815 | >>> printall(1, 2.0, third='3')
816 | TypeError: printall() got an unexpected keyword argument 'third'
817 | ```
818 |
819 |
820 |
821 |
822 |
823 |
824 | To gather keyword arguments, you can use the ** operator:
825 | >要收集关键词参数,你就可以用**运算符:
826 |
827 |
828 | ```Python
829 | def printall(*args, **kwargs):
830 | print(args, kwargs)
831 | ```
832 |
833 |
834 |
835 |
836 |
837 | You can call the keyword gathering parameter anything you want, but kwargs is a common choice. The result is a dictionary that maps keywords to values:
838 | >你可以用任意名字来命名这里的关键词收集参数,不过通常大家都用kwargs。得到的结果是一个字典,映射了关键词键名与键值:
839 |
840 |
841 | ```Python
842 | >>> printall(1, 2.0, third='3')
843 | (1, 2.0) {'third': '3'}
844 | ```
845 |
846 |
847 |
848 |
849 |
850 |
851 | If you have a dictionary of keywords and values, you can use the scatter operator, ** to call a function:
852 | >如果你有一个关键词和值组成的字典,你就可以用散射运算符,**来调用一个函数:
853 |
854 |
855 | ```Python
856 | >>> d = dict(x=1, y=2)
857 | >>> Point(**d)
858 | Point(x=1, y=2)
859 | ```
860 |
861 |
862 |
863 |
864 | Without the scatter operator, the function would treat d as a single positional argument, so it would assign d to x and complain because there’s nothing to assign to y:
865 | >不用散射运算符的话,函数会把 d 当做一个单独的位置参数,所以就会把 d 赋值股额 x,然后出错,因为没有给 y 赋值:
866 |
867 |
868 | ```Python
869 | >>> d = dict(x=1, y=2)
870 | >>> Point(d)
871 | Traceback (most recent call last): File "", line 1, in TypeError: __new__() missing 1 required positional argument: 'y'
872 | ```
873 |
874 |
875 |
876 |
877 | When you are working with functions that have a large number of parameters, it is often useful to create and pass around dictionaries that specify frequently-used options.
878 | >当你写一些有大量参数的函数的时候,就可以创建和使用一些字典,这样能把各种常用选项弄清。
879 |
880 |
881 |
882 | ##19.10 Glossary 术语列表
883 |
884 |
885 |
886 |
887 | conditional expression:
888 | An expression that has one of two values, depending on a condition.
889 | >条件表达式:一种根据一个条件来从两个值中选一个的表达式。
890 |
891 |
892 |
893 | list comprehension:
894 | An expression with a for loop in square brackets that yields a new list.
895 | >列表推导:一种用表达式, 方括号内有一个for 循环,生成一个新的列表。
896 |
897 |
898 |
899 |
900 |
901 | generator expression:
902 | An expression with a for loop in parentheses that yields a generator object.
903 | >生成器表达式:一种表达式,圆括号内放一个 for 循环,产生一个生成器对象。
904 |
905 |
906 |
907 |
908 | multiset:
909 | A mathematical entity that represents a mapping between the elements of a set and the number of times they appear.
910 | >多重集:一个数学上的概念,表示了一种从集合中元素到出现次数只见的映射关系。
911 |
912 |
913 |
914 |
915 | factory:
916 | A function, usually passed as a parameter, used to create objects.
917 | >工厂:一个函数,通常作为参数传递,用来产生对象。
918 |
919 |
920 |
921 | ##19.11 Exercises 练习
922 |
923 |
924 | ###Exercise 1 练习1
925 |
926 |
927 |
928 | The following is a function computes the binomial coefficient recursively.
929 | >线面的函数是递归地计算二项式系数的。
930 |
931 |
932 | ```Python
933 | def binomial_coeff(n, k):
934 | """Compute the binomial coefficient "n choose k".
935 | n: number of trials
936 | k: number of successes
937 | returns: int """
938 | if k == 0:
939 | return 1
940 | if n == 0:
941 | return 0
942 | res = binomial_coeff(n-1, k) + binomial_coeff(n-1, k-1)
943 | return res
944 | ```
945 |
946 |
947 |
948 |
949 |
950 |
951 |
952 | Rewrite the body of the function using nested conditional expressions.
953 | >用网状条件语句来重写一下函数体。
954 |
955 |
956 |
957 |
958 | One note: this function is not very efficient because it ends up computing the same values over and over. You could make it more efficient by memoizing (see Section 11.6). But you will find that it’s harder to memoize if you write it using conditional expressions.
959 | >一点提示:这个函数并不是很有效率,因为总是要一遍一遍地计算同样的值。你可以通过存储已有结果(参考11.6)来提高效率。但你会发现如果你用条件表达式实现,就会导致这种记忆更困难。
960 |
--------------------------------------------------------------------------------
/ThinkPython-2.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 2
2 | Date: 2015-10-23
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | # Chapter 2 Variables, expressions and statements 变量,表达式,语句
7 |
8 | One of the most powerful features of a programming language is the ability to manipulate variables. A variable is a name that refers to a value.
9 |
10 | > 编程语言最强大的功能就是操作变量。变量就是一个有值的代号。
11 |
12 | ## 2.1 Assignment statements 赋值语句
13 |
14 | An assignment statement creates a new variable and gives it a value:
15 |
16 | > 赋值语句的作用是创建一个新的变量,并且赋值给这个变量:
17 |
18 | ```python
19 | >>> message = 'And now for something completely different'
20 | >>> n = 17
21 | >>> pi = 3.141592653589793
22 | ```
23 |
24 | This example makes three assignments. The first assigns a string to a new variable named message; the second gives the integer 17 to n; the third assigns the \(approximate\) value of π to pi.
25 |
26 | > 上面就是三个赋值语句的例子。第一个是把一个字符串复制给名叫message的新变量;第二个将n赋值为整数17;第三个把圆周率的一个近似值赋给了pi这个变量。
27 |
28 | A common way to represent variables on paper is to write the name with an arrow pointing to its value. This kind of figure is called a state diagram because it shows what state each of the variables is in \(think of it as the variable’s state of mind\). Figure 2.1 shows the result of the previous example.
29 |
30 | > 平常大家在纸上对变量赋值的方法就是写下名字,然后一个箭头指向它的值。这种图解叫做状态图,因为它能指明各个变量存储的是什么内容。下图就展示了上面例子中赋值语句的结果。
31 |
32 | ---
33 |
34 | 
35 | Figure 2.1: State diagram.
36 |
37 | ---
38 |
39 | ## 2.2 Variable names 变量名称
40 |
41 | Programmers generally choose names for their variables that are meaningful—they document what the variable is used for.
42 |
43 | > 编程的人总得给变量起个有一定意义的名字才能记得住,一般情况就用名字来表示这个变量的用途了。
44 |
45 | Variable names can be as long as you like. They can contain both letters and numbers, but they can’t begin with a number. It is legal to use uppercase letters, but it is conventional to use only lower case for variables names.
46 |
47 | > 变量名称你随便起多长都可以的。包含字母或者数字都行,但是不能用数字来开头。大写字母也能用,不过还是建议都用小写字母来给变量命名,这个比较传统哈。
48 |
49 | The underscore character, \_, can appear in a name. It is often used in names with multiple words, such as your\_name or airspeed\_of\_unladen\_swallow.
50 |
51 | > 变量名里面可以有下划线\_,一般在多个单词组成的变量名里面往往用到下划线,比如your\_name等等。
52 |
53 | If you give a variable an illegal name, you get a syntax error:
54 |
55 | > 你要是给变量起名不合规则,就会出现语法错误提示了:
56 |
57 | ```Python
58 | >>> 76trombones = 'big parade'
59 | SyntaxError: invalid syntax
60 | >>> more@ = 1000000
61 | SyntaxError: invalid syntax
62 | >>> class = 'Advanced Theoretical Zymurgy'
63 | SyntaxError: invalid syntax
64 | ```
65 |
66 | 76trombones is illegal because it begins with a number. more@ is illegal because it contains an illegal character, @. But what’s wrong with class?
67 |
68 | > 第一个数字开头所以不合规则,第二个有非法字符@,第三个这个class咋不行呢?好奇吧?
69 |
70 | It turns out that class is one of Python’s keywords. The interpreter uses keywords to recognize the structure of the program, and they cannot be used as variable names.
71 |
72 | > 因为classs是Python里面的一个关键词啦。解释器要用关键词来识别程序的结构,这些关键词是不能用来做变量名的。
73 |
74 | Python 3 has these keywords:
75 |
76 | > 以下是Python3的关键词哈:
77 |
78 | ```Python
79 | False class finally is
80 | return None continue for lambda
81 | try True def from nonlocal
82 | while and del global not
83 | with as elif if or
84 | yield assert else import pass
85 | break except in raise
86 | ```
87 |
88 | You don’t have to memorize this list. In most development environments, keywords are displayed in a different color; if you try to use one as a variable name, you’ll know.
89 |
90 | > 你不用去记忆这些哈。因为一般大多数的开发环境里面,关键词都会有区别于普通代码的颜色提示你,你要是用他们做变量名了,一看就会知道的。
91 |
92 | ## 2.3 Expressions and statements 表达式和语句
93 |
94 | An expression is a combination of values, variables, and operators. A value all by itself is considered an expression, and so is a variable, so the following are all legal expressions:
95 |
96 | > 表达式是数值,变量和操作符的组合。单个值本身也被当作一个表达式,变量也是如此,下面这些例子都是一些正确表达式:
97 |
98 | ```Python
99 | >>> 42
100 | 42
101 | >>> n
102 | 17
103 | >>> n + 25
104 | 42
105 | ```
106 |
107 | When you type an expression at the prompt, the interpreter evaluates it, which means that it finds the value of the expression. In this example, n has the value 17 and n + 25 has the value 42.
108 |
109 | > 当你在提示符后面敲出一个表达式,解释器就判断一下,他会找到这个表达式的值。在本节的例子中,n的值是17,所以n+25就是42了。
110 |
111 | A statement is a unit of code that has an effect, like creating a variable or displaying a value.
112 |
113 | > 语句是一组具有某些效果的代码,比如创建变量,或者显示值。
114 |
115 | ```Python
116 | >>> n = 17
117 | >>> print(n)
118 | ```
119 |
120 | The first line is an assignment statement that gives a value to n. The second line is a print statement that displays the value of n.
121 |
122 | > 上面第一个就是赋值语句,给n赋值。第二行是显示n的值。
123 |
124 | When you type a statement, the interpreter executes it, which means that it does whatever the statement says. In general, statements don’t have values.
125 |
126 | > 输入语句的时候,解释器会执行它,就是会按照语句所说的去做。一般语句是没有值的。
127 |
128 | ## 2.4 Script mode 脚本模式
129 |
130 | So far we have run Python in interactive mode, which means that you interact directly with the interpreter. Interactive mode is a good way to get started, but if you are working with more than a few lines of code, it can be clumsy.
131 |
132 | > 以上我们一直在用Python的交互模式,就是直接咱们人跟解释器来交互。开始学的时候这样挺好的,但如果你要想一次运行多行代码,这样就很不方便了。
133 |
134 | The alternative is to save code in a file called a script and then run the interpreter in script mode to execute the script. By convention, Python scripts have names that end with .py.
135 |
136 | > 所以就有另一种选择了,把代码保存成脚本,然后用脚本模式让解释器来运行这些脚本。通常Python脚本文件的扩展名是.py。
137 |
138 | If you know how to create and run a script on your computer, you are ready to go. Otherwise I recommend using PythonAnywhere again. I have posted instructions for running in script mode at [http://tinyurl.com/thinkpython2e](http://tinyurl.com/thinkpython2e).
139 |
140 | > 如果你知道怎么创建和运行脚本,那就尽管在自己电脑上尝试好了。否则我就建议你还是用PythonAnywhere。关于脚本模式的介绍我放到网上了,打开这个链接([http://tinyurl.com/thinkpython2e)去看下哈。](http://tinyurl.com/thinkpython2e)去看下哈。)
141 |
142 | Because Python provides both modes, you can test bits of code in interactive mode before you put them in a script. But there are differences between interactive mode and script mode that can be confusing.
143 |
144 | > Python两种模式都支持,所以你可以先用交互模式做点测试,然后再写成脚本。但是两种模式之间有些区别的,所以可能也挺麻烦。
145 | > For example, if you are using Python as a calculator, you might type:
146 | > 举个例子哈,比如咱们把Python当计算器用,你输入以下内容:
147 |
148 | ```Python
149 | >>> miles = 26.2
150 | >>> miles * 1.61
151 | 42.182
152 | ```
153 |
154 | The first line assigns a value to miles, but it has no visible effect. The second line is an expression, so the interpreter evaluates it and displays the result. It turns out that a marathon is about 42 kilometers.
155 |
156 | > 第一行给miles这个变量赋初值(译者注:26.2英里是马拉松比赛全程长度),但是看着没啥效果。第二行是一个表达式,解释器会计算这个表达式,然后把结果输出。结果就是把马拉松全程长度从英里换算成公里,答案是42公里哈。
157 |
158 | But if you type the same code into a script and run it, you get no output at all. In script mode an expression, all by itself, has no visible effect. Python actually evaluates the expression, but it doesn’t display the value unless you tell it to:
159 |
160 | > 不过你要是直接把这些代码存成脚本然后运行,是啥都看不到的,没有输出。在脚本模式表达式是没有明显效果的。Python确实会计算这些表达式,但不显示结果,想看到结果你就得告诉他输出一下:
161 |
162 | ```Python
163 | miles = 26.2
164 | print(miles * 1.61)
165 | ```
166 |
167 | This behavior can be confusing at first.
168 |
169 | > 这种情况开始还挺让人混乱的。
170 |
171 | A script usually contains a sequence of statements. If there is more than one statement, the results appear one at a time as the statements execute.For example, the script:
172 |
173 | > 脚本一般都是包含了一系列的语句。如果语句超过一条,每个语句执行的时候都会显示结果。比如下面这个:
174 |
175 | ```python
176 | print(1)
177 | x = 2
178 | print(x)
179 | ```
180 |
181 | produces the output
182 |
183 | > 输出的结果如下
184 |
185 | ```Python
186 | 1
187 | 2
188 | ```
189 |
190 | The assignment statement produces no output.
191 |
192 | > 赋值语句是不会有任何输出的。
193 |
194 | To check your understanding, type the following statements in the Python interpreter and see what they do:
195 |
196 | > 检查下你理解了没哈,把下面这些语句输入到Python解释器,看看会发生什么:
197 |
198 | ```Python
199 | 5 x = 5 x + 1
200 | ```
201 |
202 | Now put the same statements in a script and run it. What is the output? Modify the script by transforming each expression into a print statement and then run it again.
203 |
204 | > 现在再把同样的语句输入到脚本中,然后用Python来运行一下。看看输出是啥样的?把脚本中的表达式修改一下,每一个都加一个打印语句再试试。
205 |
206 | ## 2.5 Order of operations 运算符优先级
207 |
208 | When an expression contains more than one operator, the order of evaluation depends on the order of operations. For mathematical operators, Python follows mathematical convention. The acronym PEMDAS is a useful way to remember the rules:
209 |
210 | > 表达式可能会包含不止一个运算符,这些不同的运算先后次序就是运算符的优先级。对于数学运算符来说,Python就遵循着数学上的规则。下面这个PEMDAS、是用来记忆这些优先规则的好方法:
211 |
212 | * Parentheses have the highest precedence and can be used to force an expression to evaluate in the order you want. Since expressions in parentheses are evaluated first, 2 \*\* \(3-1\) is 4, and \(1+1\)\*\*\(5-2\) is 8. You can also use parentheses to make an expression easier to read, as in\(minute _ 100\) / 60, even if it doesn’t change the result.
213 |
214 | > 括号内的内容最优先,大家可以用括号来强制某系表达式有限计算。所以2\*\*(3-1)就等于4了,(1+1)\*\*(5-2)就是2的立方,等于8。使用括号也有助于让你的表达式读起来更好理解,比如\(minute _ 100\) / 60,这个也不影响计算结果,不过看起来易于理解。
215 |
216 | * Exponentiation has the next highest precedence, so 1 + 2\*\*3 is 9, not 27, and 2 \* 3\*\*2 is 18, not 36.
217 |
218 | > 除了括号,所有运算符中,乘方最优先,所以1 + 2\*\*3的结果是9而不是27,2\*3\*\*2结果是18,而不是36。
219 |
220 | * Multiplication and Division have higher precedence than Addition andSubtraction. So 2\*3-1 is 5, not 4, and 6+4/2 is 8, not 5.
221 |
222 | > 乘除运算比加减优先,译者认为大家都知道了,这个我就不细说了。
223 |
224 | * Operators with the same precedence are evaluated from left to right \(except exponentiation\). So in the expression degrees / 2 \* pi, the division happens first and the result is multiplied by pi. To divide by 2 π, you can use parentheses or write degrees / 2 / pi.
225 |
226 | > 同类运算符从左往右来进行,乘方除外。这个也不细说了,很简单。
227 |
228 | I don’t work very hard to remember the precedence of operators. If I can’t tell by looking at the expression, I use parentheses to make it obvious.
229 |
230 | > 我不会花很大力气来记忆这些运算符的优先级。如果我记不起来,就用括号来让优先级明确一些就好了。
231 |
232 | ## 2.6 String operations 字符串操作
233 |
234 | In general, you can’t perform mathematical operations on strings, even if the strings look like numbers, so the following are illegal:
235 |
236 | > 一般情况下,咱们不能对字符串进行数学运算的,即使字符串看上去像是数字也不行,所以以下这些都是非法操作:
237 |
238 | ```Python
239 | '2'-'1' 'eggs'/'easy' 'third'*'a charm'
240 | ```
241 |
242 | But there are two exceptions, + and \*.
243 |
244 | > 不过+和\*可以用在字符串上面。
245 |
246 | The + operator performs string concatenation, which means it joins the strings by linking them end-to-end. For example:
247 |
248 | > +加号的意思就是字符串拼接了,会把两个字符串拼到一起,如下所示:
249 |
250 | ```Python
251 | >>> first = 'throat'
252 | >>> second = 'warbler'
253 | >>> first + second
254 | throatwarbler
255 | ```
256 |
257 | The _ operator also works on strings; it performs repetition. For example,'Spam'_3 is 'SpamSpamSpam'. If one of the values is a string, the other has to be an integer.
258 |
259 | > _星号也就是乘法运算符也可以用在字符串上面,效果就是重复。比如'Spam'_3 结果就是
260 | > 'SpamSpamSpam',重复了三次。需要注意的是字符串必须用整数去乘。
261 |
262 | This use of + and _ makes sense by analogy with addition and multiplication. Just as 4_3 is equivalent to 4+4+4, we expect 'Spam'\*3 to be the same as'Spam'+'Spam'+'Spam', and it is. On the other hand, there is a significant way in which string concatenation and repetition are different from integer addition and multiplication. Can you think of a property that addition has that string concatenation does not?
263 |
264 | > 这种加法和乘法实际上就是拼接和重复的意思。就像4_3等同于4+4+4一样,'Spam'_3 也就等于'Spam'+’Spam’+’Spam'。另外一方面,字符串的拼接重复与整数的加法乘法也有显著区别。你能想到加法具有些特性是字符拼接所不具有的么?
265 |
266 | ## 2.7 Comments 注释
267 |
268 | As programs get bigger and more complicated, they get more difficult to read. Formal languages are dense, and it is often difficult to look at a piece of code and figure out what it is doing, or why.
269 |
270 | > 程序会越来越庞大,也越复杂了,读起来就会更难了。公式语言很密集,靠阅读来理解代码,总是很困难的。
271 |
272 | For this reason, it is a good idea to add notes to your programs to explain in natural language what the program is doing. These notes are called comments, and they start with the \# symbol:
273 |
274 | > 为了解决阅读的困难,咱们就可以添加一些笔记到代码中,把程序的功能用自然语言来解释一下。这种笔记就叫注释了,使用井号\#来开头的:
275 |
276 | ```Python
277 | # compute the percentage of the hour that has elapsed percentage = (minute * 100) / 60
278 | ```
279 |
280 | In this case, the comment appears on a line by itself. You can also put comments at the end of a line:
281 |
282 | > 注释可以另起一行,也可以放到行末尾:
283 |
284 | ```Python
285 | percentage = (minute * 100) / 60 # percentage of an hour
286 | ```
287 |
288 | Everything from the \# to the end of the line is ignored—it has no effect on the execution of the program
289 |
290 | > 井号\#后面的内容都会被忽略,因此不会影响程序的运行结果。
291 |
292 | Comments are most useful when they document non-obvious features of the code. It is reasonable to assume that the reader can figure out what the code does; it is more useful to explain why.
293 |
294 | > 一般注释都是用来解释代码的一些不明显的特性。一般情况下读代码的人应该能理解代码的功能是什么,所以用注释多是要解释这样做的目的是什么。
295 |
296 | This comment is redundant with the code and useless:
297 |
298 | > 这个注释就显然是多余的,根本没必要:
299 |
300 | ```Python
301 | v = 5 # assign 5 to v
302 | ```
303 |
304 | This comment contains useful information that is not in the code:
305 |
306 | > 这种注释包含了重要信息,就很重要了:
307 |
308 | ```python
309 | v = 5 # velocity in meters/second.
310 | ```
311 |
312 | Good variable names can reduce the need for comments, but long names can make complex expressions hard to read, so there is a tradeoff.
313 |
314 | > 变量命名得当的话,就没必要用太多注释了,不过名字要是太长了,表达式读起来也挺麻烦,所以就得权衡着来了。
315 |
316 | ## 2.8 Debugging 调试
317 |
318 | Three kinds of errors can occur in a program: syntax errors, runtime errors, and semantic errors. It is useful to distinguish between them in order to track them down more quickly.
319 |
320 | > 程序一般会有三种错误:语法错误,运行错误和语义错误。区分这三种错误有助于更快速地追踪错误。
321 |
322 | * Syntax error:
323 | “Syntax” refers to the structure of a program and the rules about that structure. For example, parentheses have to come in matching pairs, so\(1 + 2\) is legal, but 8\) is a syntax error.
324 | If there is a syntax error anywhere in your program, Python displays an error message and quits, and you will not be able to run the program. During the first few weeks of your programming career, you might spend a lot of time tracking down syntax errors. As you gain experience, you will make fewer errors and find them faster.
325 |
326 | > 语法错误Syntax error:
327 | > 语法是指程序的结构和规则。比如括号要成对用。如果你的程序有某个地方出现了语法错误,Python会显示出错信息并退出,程序就不能运行了。最开始学习编程的这段时间,你遇到的最常见的估计就是这种情况。等你经验多了,基本就犯的少了,而且也很容易发现了。
328 |
329 | * Runtime error:
330 | The second type of error is a runtime error, so called because the error does not appear until after the program has started running. These errors are also called exceptions because they usually indicate that something exceptional \(and bad\) has happened.
331 | Runtime errors are rare in the simple programs you will see in the first few chapters, so it might be a while before you encounter one.
332 |
333 | > 运行错误Runtime error:
334 | > 第二种错误就是运行错误,显而易见了,就是直到运行的时候才会出现的错误。这种错误也被叫做异常,因为一般表示一些意外的尤其是比较糟糕的情况发生了。
335 |
336 | * Semantic error:
337 | The third type of error is “semantic”, which means related to meaning. If there is a semantic error in your program, it will run without generating error messages, but it will not do the right thing. It will do something else. Specifically, it will do what you told it to do.
338 | Identifying semantic errors can be tricky because it requires you to work backward by looking at the output of the program and trying to figure out what it is doing.
339 |
340 | > 语义错误Semantic error:
341 | > 第三种就是语义错误,顾名思义,是跟意义相关。这种错误是指你的程序运行没问题,也不产生错误信息,但不能正确工作。程序可能做一些和设计目的不同的事情。发现语义错误特别不容易,需要你仔细回顾代码和程序输出,要搞清楚到底程序做了什么。
342 |
343 | ## 2.9 Glossary 术语列表
344 |
345 | variable:
346 | A name that refers to a value.
347 | 变量:有值的量。
348 |
349 | > assignment:
350 |
351 | A statement that assigns a value to a variable.
352 |
353 | > 赋值:给一个变量赋予值。
354 |
355 | state diagram:
356 | A graphical representation of a set of variables and the values they refer to.
357 |
358 | > 状态图:图形化表征每个变量的值。
359 |
360 | keyword:
361 | A reserved word that is used to parse a program; you cannot use keywords like if, def, and while as variable names.
362 |
363 | > 关键词:系统保留的用于解析程序的词,不能用关键词当做变量名。
364 |
365 | operand:
366 | One of the values on which an operator operates.
367 |
368 | > 运算数:运算符来进行运算操作的数值。
369 |
370 | expression:
371 | A combination of variables, operators, and values that represents a single result.
372 |
373 | > 表达式:一组变量、运算数的组合,会产生单值作为结果。
374 |
375 | evaluate:
376 | To simplify an expression by performing the operations in order to yield a single value.
377 |
378 | > 求解:把表达式所表示的运算计算出来,得到一个单独的值。
379 |
380 | statement:
381 | A section of code that represents a command or action. So far, the statements we have seen are assignments and print statements.
382 |
383 | > 声明:一组表示一种命令或者动作的代码,目前我们了解的只有赋值语句和打印语句。
384 |
385 | execute:
386 | To run a statement and do what it says.
387 |
388 | > 运行:将一条语句进行运行。
389 |
390 | interactive mode:
391 | A way of using the Python interpreter by typing code at the prompt.
392 |
393 | > 交互模式:在提示符后输入代码,让解释器来运行代码的模式。
394 |
395 | script mode:
396 | A way of using the Python interpreter to read code from a script and run it.
397 |
398 | > 脚本模式:将代码保存成脚本文件,用解释器运行的模式。
399 |
400 | script:
401 | A program stored in a file.
402 |
403 | > 脚本:程序以文本形式存成的文件。
404 |
405 | order of operations:
406 | Rules governing the order in which expressions involving multiple operators and operands are evaluated.
407 |
408 | > 运算符优先级:不同运算符和运算数进行计算的优先顺序。
409 |
410 | concatenate:
411 | To join two operands end-to-end.
412 |
413 | > 拼接:把两个运算对象相互连接到一起。
414 |
415 | comment:
416 | Information in a program that is meant for other programmers \(or anyone reading the source code\) and has no effect on the execution of the program.
417 |
418 | > 注释:程序中用来解释代码含义和运行效果的备注信息,通常给阅读代码的人准备的。
419 |
420 | syntax error:
421 | An error in a program that makes it impossible to parse \(and therefore impossible to interpret\).
422 |
423 | > 语法错误:程序语法上的错误,导致程序不能被解释器解译,就不能运行了。
424 |
425 | exception:
426 | An error that is detected while the program is running.
427 |
428 | > 异常:程序运行的时候被探测到的错误。
429 |
430 | semantics:
431 | The meaning of a program.
432 |
433 | > 语义:程序的意义。
434 |
435 | semantic error:
436 | An error in a program that makes it do something other than what the programmer intended.
437 |
438 | > 语义错误:程序运行的结果和料想的不一样,没有完成设计的功能,而是干了点其他的事情。
439 |
440 | ## 2.10 Exercises 练习
441 |
442 | ### Exercise 1 练习1
443 |
444 | Repeating my advice from the previous chapter, whenever you learn a new feature, you should try it out in interactive mode and make errors on purpose to see what goes wrong.
445 |
446 | > 像上一章一样,按我建议的,不论学了什么新内容,你都试着在交互模式上故意犯点错误,看看会怎么样。
447 |
448 | * We’ve seen that n = 42 is legal. What about 42 = n?
449 | > 我们都看到了n=42是可以的,那42=n怎么样?
450 | * How about x = y = 1?
451 | > 再试试x=y=1呢?
452 | * In some languages every statement ends with a semi-colon, ;. What happens if you put a semi-colon at the end of a Python statement?
453 | > 有的语言每个语句结尾都必须有个单引号或者分号,试试在Python句末放个会咋样?
454 | * What if you put a period at the end of a statement?
455 | > 句尾放个句号试试呢?
456 | * In math notation you can multiply x and y like this: x y. What happens if you try that in Python?
457 | > 数学上你可以把x和y相乘写成xy,Python里面你这么试试看?
458 |
459 | ### Exercise 2
460 |
461 | Practice using the Python interpreter as a calculator:
462 | 1. The volume of a sphere with radius r is 4/3 π r3. What is the volume of a sphere with radius 5?
463 | 2. Suppose the cover price of a book is $24.95, but bookstores get a 40% discount. Shipping costs $3 for the first copy and 75 cents for each additional copy. What is the total wholesale cost for 60 copies?
464 | 3. If I leave my house at 6:52 am and run 1 mile at an easy pace \(8:15 per mile\), then 3 miles at tempo \(7:12 per mile\) and 1 mile at easy pace again, what time do I get home for breakfast?
465 |
466 | > 把Python解释器当做计算器来做下面的练习:
467 | > 1. 球体体积是三分之四倍的圆周率乘以半径立方,求半径为5的球体体积。
468 | > 2. 假如一本书的封面标价是24.95美元,书店打六折。第一本运费花费3美元,后续每增加一本的运费是75美分。问买60本一共得花多少钱呢?
469 | > 3. 我早上六点五十二分出门离家,以8:15的节奏跑了一英里,又以7:12的节奏跑了三英里,然后又是8:15的节奏跑一英里,回到家吃饭是几点?
470 |
471 |
472 |
473 |
--------------------------------------------------------------------------------
/ThinkPython-7.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 7
2 | Date: 2015-11-19
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 7 Iteration 迭代
7 |
8 | This chapter is about iteration, which is the ability to run a block of statements repeatedly. We saw a kind of iteration, using recursion, in Section 5.8. We saw another kind, using a for loop, in Section 4.2. In this chapter we’ll see yet another kind, using a while statement. But first I want to say a little more about variable assignment.
9 | >这一章我们讲迭代,简单说就是指重复去运行一部分代码。在5.8的时候我们接触了一种迭代——递归。在4.2我们还学了另外一种迭代——for循环。在本章,我们会见到新的迭代方式:whie语句。但我要先再稍微讲一下变量赋值。
10 |
11 | ##7.1 Reassignment 再赋值
12 |
13 | As you may have discovered, it is legal to make more than one assignment to the same variable. A new assignment makes an existing variable refer to a new value (and stop referring to the old value).
14 | >你可能已经发现了,对同一个变量可以多次进行赋值。一次新的赋值使得已有的变量获得新的值(也就不再有旧的值了。)
15 | >(译者注:这个其实中文很好理解,英文当中词汇逻辑关系比较紧密,但灵活程度不如中文高啊。)
16 |
17 | ```Python
18 | >>> x = 5
19 | >>> x
20 | 5
21 | >>> x = 7
22 | >>> x
23 | 7
24 | ```
25 |
26 |
27 | The first time we display x, its value is 5; the second time, its value is 7.
28 | >第一次显示x的值,是5,第二次,就是7了。
29 |
30 |
31 | Figure 7.1 shows what reassignment looks like in a state diagram.
32 | >图7.1表示了再赋值的操作在状态图中的样子。
33 |
34 |
35 |
36 | At this point I want to address a common source of confusion. Because Python uses the equal sign (=) for assignment, it is tempting to interpret a statement like a = b as a mathematical proposition of equality; that is, the claim that a and b are equal. But this interpretation is wrong.
37 | >这里我就要强调一下大家常发生的误解。因为Python使用单等号(=)来赋值,所以有的人会以为像a=b这样的语句就如同数学上的表达一样来表达两者相等,这种想法是错误的!
38 |
39 |
40 | First, equality is a symmetric relationship and assignment is not. For example, in mathematics, if a=7 then 7=a. But in Python, the statement a = 7 is legal and 7 = a is not.
41 | >首先,数学上的等号所表示的相等是一个对称的关系,而Python中等号的赋值操作是不对称的。比如,在数学上,如果a=7,那么7=a。而在Python,a=7这个是合乎语法的,而7=a是错误的。
42 | >(译者注:这里就是说Python中等号是一种单向的运算,就是把等号右边的值赋给等号左边的变量,而Python中其实也有数学上相等判断的表达式,就是双等号(==),这个是有对称性的,就是说a==b,那么b==a,或者a==3,3==a也可以。)
43 |
44 |
45 | Also, in mathematics, a proposition of equality is either true or false for all time. If a=b now, then a will always equal b. In Python, an assignment statement can make two variables equal, but they don’t have to stay that way:
46 | >另外在数学上,一个相等关系要么是真,要么是假。比如a=b,那么a就会永远等于b。在Python里面,赋值语句可以让两个变量相等,但可以不始终都相等,如下所示:
47 |
48 |
49 | ```Python
50 | >>> a = 5
51 | >>> b = a # a and b are now equal a和b相等了
52 | >>> a = 3 # a and b are no longer equal 现在a和b就不相等了
53 | >>> b
54 | 5
55 | ```
56 |
57 |
58 | The third line changes the value of a but does not change the value of b, so they are no longer equal.
59 | >第三行改变了a的值,但没有改变b的值,所以它们就不再相等了。
60 |
61 | Reassigning variables is often useful, but you should use it with caution. If the values of variables change frequently, it can make the code difficult to read and debug.
62 | >对变量进行再赋值总是很有用的,但你用的时候要做好备注和提示。如果变量的值频繁变化,就可能让代码难以阅读和调试。
63 |
64 | ________________________________________
65 | 
66 | Figure 7.1: State diagram.
67 | ________________________________________
68 |
69 |
70 |
71 |
72 | ##7.2 Updating variables 更新变量
73 |
74 |
75 |
76 | A common kind of reassignment is an update, where the new value of the variable depends on the old.
77 | >最常见的一种再赋值就是对变量进行更新,这种情况下新的值是在旧值基础上进行修改得到的。
78 |
79 | ```Python
80 | >>> x = x + 1
81 | ```
82 |
83 |
84 |
85 |
86 |
87 | This means “get the current value of x, add one, and then update x with the new value.”
88 | If you try to update a variable that doesn’t exist, you get an error, because Python evaluates the right side before it assigns a value to x:
89 | >上面的语句的意思是:获取x当前的值,在此基础上加1,然后把结果作为新值赋给x。如果你对不存在的变量进行更新,你就会得到错误了,因为Python要先进行等号右边的运算,然后才能赋值给x。
90 |
91 |
92 |
93 | ```Python
94 | >>> x = x + 1
95 | NameError: name 'x' is not defined
96 | ```
97 |
98 |
99 |
100 | Before you can update a variable, you have to initialize it, usually with a simple assignment:
101 | >在你更新一个变量之前,你要先初始化一下,一般就是简单赋值一下就可以了:
102 |
103 | ```Python
104 | >>> x = 0
105 | >>> x = x + 1
106 | ```
107 |
108 | Updating a variable by adding 1 is called an increment; subtracting 1 is called a decrement.
109 | >对一个变量每次加1也可以叫做一种递增,每次减去1就可以叫做递减了。
110 |
111 |
112 |
113 | ##7.3 The while statement 循环:While语句
114 |
115 |
116 |
117 | Computers are often used to automate repetitive tasks. Repeating identical or similar tasks without making errors is something that computers do well and people do poorly. In a computer program, repetition is also called iteration.
118 | >计算机经常被用来自动执行一些重复的任务。重复同样的或者相似的任务,而不出错,这是计算机特别擅长的事情,咱们人就做不到了。在一个计算机程序里面,重复操作也被叫做迭代。
119 |
120 |
121 | We have already seen two functions, countdown and print_n, that iterate using recursion. Because iteration is so common, Python provides language features to make it easier. One is the for statement we saw in Section 4.2. We’ll get back to that later. Another is the while statement. Here is a version of countdown that uses a while statement:
122 | >我们已经见过两种使用了递归来进行迭代的函数:倒计时函数countdown,以及n次输出函数print_n。Python还提供了一些功能来简化迭代,因为迭代用的很普遍。其中一个就是我们在4.2中见到的for循环语句。往后我们还要复习一下它。另外一个就是while循环语句。下面就是一个使用了while循环语句来实现的倒计时函数countdown:
123 |
124 |
125 | ```Python
126 | def countdown(n):
127 | while n > 0:
128 | print(n)
129 | n = n - 1
130 | print('Blastoff!')
131 | ```
132 |
133 | You can almost read the while statement as if it were English. It means, “While n is greater than 0, display the value of n and then decrement n. When you get to 0, display the word Blastoff!”
134 | >while循环语句读起来很容易,几乎就像是英语一样简单。这个函数的意思是:当n大于0,就输出n的值,然后对n减1,到n等于0的时候,就输出单词『Blastoff』。
135 |
136 | More formally, here is the flow of execution for a while statement:
137 | >更正式一点,下面是一个while循环语句的执行流程:
138 |
139 | 1. Determine whether the condition is true or false.
140 | >判断循环条件的真假。
141 |
142 | 2. If false, exit the while statement and continue execution at the next statement.
143 | >如果是假的,退出while语句,继续运行后面的语句。
144 |
145 | 3. If the condition is true, run the body and then go back to step 1.
146 | >如果条件为真,执行循环体,然后再调回到第一步。
147 |
148 |
149 | This type of flow is called a loop because the third step loops back around to the top.
150 | The body of the loop should change the value of one or more variables so that the condition becomes false eventually and the loop terminates.
151 | >这种类型的运行流程叫做循环,因为第三步会循环到第一步。循环体内要改变一个或者更多变量的值,这样循环条件最终才能变成假,然后循环才能终止。
152 |
153 |
154 | Otherwise the loop will repeat forever, which is called an infinite loop. An endless source of amusement for computer scientists is the observation that the directions on shampoo, “Lather, rinse, repeat”, are an infinite loop.
155 | >否则的话,条件不能为假,循环不能停止,这就叫做无限循环。计算机科学家有一个笑话,就是看到洗发液的说明:起泡,冲洗,重复;这就是一个无限循环。
156 |
157 |
158 | In the case of countdown, we can prove that the loop terminates: if n is zero or negative, the loop never runs. Otherwise, n gets smaller each time through the loop, so eventually we have to get to 0.
159 | >在倒计时函数countdown里面,咱们能够保证有办法让循环终止:只要n小于等于0了,循环就不进行了。否则的话,n每次就会通过循环来递减,最终还是能到0的。
160 |
161 |
162 | For some other loops, it is not so easy to tell. For example:
163 | >其他一些循环就不那么好描述了。比如:
164 |
165 | ```Python
166 | def sequence(n):
167 | while n != 1:
168 | print(n)
169 | if n % 2 == 0: # n is even
170 | n = n / 2
171 | else: # n is odd
172 | n = n*3 + 1
173 | ```
174 |
175 |
176 |
177 | The condition for this loop is n != 1, so the loop will continue until n is 1, which makes the condition false.
178 | >这个循环的判断条件是n不等于1,所以循环一直进行,直到n等于1了,条件为假,就不再循环了。
179 |
180 | Each time through the loop, the program outputs the value of n and then checks whether it is even or odd. If it is even, n is divided by 2. If it is odd, the value of n is replaced with n*3 + 1. For example, if the argument passed to sequence is 3, the resulting values of n are 3, 10, 5, 16, 8, 4, 2, 1.
181 | >每次循环的时候,程序都输出n的值,然后检查一下是偶数还是奇数。如果是偶数,就把n除以2。如果是奇数,就把n替换为n乘以3再加1的值。比如让这个函数用3做参数,也就是sequence(3),得到的n的值就依次为:3, 10, 5, 16, 8, 4, 2, 1.
182 |
183 |
184 | Since n sometimes increases and sometimes decreases, there is no obvious proof that n will ever reach 1, or that the program terminates. For some particular values of n, we can prove termination. For example, if the starting value is a power of two, n will be even every time through the loop until it reaches 1. The previous example ends with such a sequence, starting with 16.
185 | >有时候n在增加,有时候n在降低,所以没有明显证据表明n最终会到1而程序停止。对于一些特定的n值,我们能够确保循环的终止。例如如果起始值是一个2的倍数,n每次循环过后依然是偶数,直到到达1位置。之前的例子都最终得到了一个数列,从16开始的就是了。
186 |
187 |
188 |
189 | The hard question is whether we can prove that this program terminates for all positive values of n. So far, no one has been able to prove it or disprove it!
190 | See [WikiPedia](http://en.wikipedia.org/wiki/Collatz_conjecture)
191 | >真正的难题是,我们能否证明这个程序对任意正数的n值都能终止循环。目前为止,没有人能够证明或者否定这个命题。
192 | 参考[维基百科](http://en.wikipedia.org/wiki/Collatz_conjecture)
193 |
194 |
195 | As an exercise, rewrite the function print_n from Section 5.8 using iteration instead of recursion.
196 | >做一个练习,把5.8里面的那个n次打印函数print_n用迭代的方法来实现。
197 |
198 |
199 | ##7.4 break 中断
200 |
201 | Sometimes you don’t know it’s time to end a loop until you get half way through the body. In that case you can use the break statement to jump out of the loop.
202 | >有时候你不知道啥时候终止循环,可能正好在中间循环体的时候要终止了。这时候你就可以用break语句来跳出循环。
203 |
204 | For example, suppose you want to take input from the user until they type done. You could write:
205 | >比如,假设你要让用户输入一些内容,当他们输入done的时候结束。你就可以用如下的方法实现:
206 |
207 |
208 |
209 | ```Python
210 | while True:
211 | line = input('> ')
212 | if line == 'done':
213 | break
214 | print(line)
215 | print('Done!')
216 | ```
217 |
218 |
219 |
220 | The loop condition is True, which is always true, so the loop runs until it hits the break statement.
221 | >循环条件就是true,意味条件总是真的,所以循环就一直进行,一直到触发了break语句才跳出。
222 |
223 |
224 |
225 | Each time through, it prompts the user with an angle bracket. If the user types done, the break statement exits the loop. Otherwise the program echoes whatever the user types and goes back to the top of the loop. Here’s a sample run:
226 | >每次循环的时候,程序都会有一个大于号>来提示用户。如果用输入了done,break语句就会让程序跳出循环。否则的话程序会重复用户输入的内容,然后回到循环的头部。下面就是一个简单的运行例子:
227 |
228 | ```Python
229 | >not done
230 | >not done
231 | >done
232 | Done!
233 | ```
234 |
235 |
236 | This way of writing while loops is common because you can check the condition anywhere in the loop (not just at the top) and you can express the stop condition affirmatively (“stop when this happens”) rather than negatively (“keep going until that happens”).
237 | >这种while循环的写法很常见,因为这样你可以在循环的任何一个部位对条件进行检测,而不仅仅是循环的头部,你可以确定地表达循环停止的条件(在这种情况下就停止了),而不是消极地暗示『程序会一直运行,直到某种情况』。
238 |
239 |
240 | ##7.5 Square roots 平方根
241 |
242 | Loops are often used in programs that compute numerical results by starting with an approximate answer and iteratively improving it.
243 | >循环经常被用于进行数值运算的程序中,这种程序往往是有一个近似值作为初始值,然后逐渐迭代去改进以接近真实值。
244 |
245 |
246 | For example, one way of computing square roots is Newton’s method. Suppose that you want to know the square root of a. If you start with almost any estimate, x, you can compute a better estimate with the following formula:
247 | >比如,可以用牛顿法来计算平方根。加入你要知道一个数a的平方根。如果你用任意一个估计值x来开始,你可以用下面的公式获得一个更接近的值:
248 |
249 |
250 | $$y = \frac{x + \frac{a}{x}}{2}$$
251 |
252 |
253 | For example, if a is 4 and x is 3:
254 | >比如,如果a是3,x设为3:
255 |
256 |
257 | ```Python
258 | >>> a = 4
259 | >>> x = 3
260 | >>> y = (x + a/x) / 2
261 | >>> y
262 | 2.16666666667
263 | ```
264 |
265 |
266 |
267 |
268 | The result is closer to the correct answer (square root of 4 is 2). If we repeat the process with the new estimate, it gets even closer:
269 | >得到的结果比初始值3更接近真实值(4的平方根是2)。如果我们用这个结果做新的估计值来重复这个操作,结果就更加接近了:
270 |
271 | ```Python
272 | >>> x = y
273 | >>> y = (x + a/x) / 2
274 | >>> y 2.00641025641
275 | ```
276 |
277 |
278 | After a few more updates, the estimate is almost exact:
279 | >这样进行一些次重复之后,估计值就几乎很准确了:
280 |
281 |
282 | ```Python
283 | >>> x = y
284 | >>> y = (x + a/x) / 2
285 | >>> y 2.00001024003
286 | >>> x = y
287 | >>> y = (x + a/x) / 2
288 | >>> y 2.00000000003
289 | ```
290 |
291 | In general we don’t know ahead of time how many steps it takes to get to the right answer, but we know when we get there because the estimate stops changing:
292 | >一般情况下,我们不能提前知道到达正确结果需要多长时间,但是当估计值不再有明显变化的时候我们就知道了:
293 |
294 | ```Python
295 | >>> x = y
296 | >>> y = (x + a/x) / 2
297 | >>> y 2.0
298 | >>> x = y
299 | >>> y = (x + a/x) / 2
300 | >>> y 2.0
301 | ```
302 |
303 |
304 | When y == x, we can stop. Here is a loop that starts with an initial estimate, x, and improves it until it stops changing:
305 | >当y和x相等的时候,我们就可以停止了。下面这个循环中,用一个初始值x来开始循环,然后进行改进,一直到x的值不再变化为止:
306 |
307 |
308 |
309 | ```Python
310 | while True:
311 | print(x)
312 | y = (x + a/x) / 2
313 | if y == x:
314 | break
315 | x = y
316 | ```
317 |
318 |
319 | For most values of a this works fine, but in general it is dangerous to test float equality. Floating-point values are only approximately right: most rational numbers, like 1/3, and irrational numbers, like √2, can’t be represented exactly with a float.
320 | >对大多数值来说,这个循环都挺管用的,但一般来说用浮点数来测试等式是很危险的。浮点数的值只能是近似正确:大多数的有理数,比如1/3,以及无理数,比如根号2,都不能用浮点数来准确表达的。
321 |
322 |
323 | Rather than checking whether x and y are exactly equal, it is safer to use the built-in function abs to compute the absolute value, or magnitude, of the difference between them:
324 | >相比之下,与其对比x和y是否精确相等,倒不如以下方法更安全:用内置的绝对值函数来计算一下差值的绝对值,也叫做数量级。
325 |
326 | ```Python
327 | if abs(y-x) < epsilon:
328 | break
329 | ```
330 |
331 |
332 | Where epsilon has a value like 0.0000001 that determines how close is close enough.
333 | >这里可以让epsilon的值为like 0.0000001,差值比这个小就说明已经足够接近了。
334 |
335 |
336 | ##7.6 Algorithms 算法
337 |
338 |
339 | Newton’s method is an example of an algorithm: it is a mechanical process for solving a category of problems (in this case, computing square roots).
340 | >牛顿法是算法的一个例子:通过一系列机械的步骤来解决一类问题(在本章中是用来计算平方根)。
341 |
342 |
343 | To understand what an algorithm is, it might help to start with something that is not an algorithm. When you learned to multiply single-digit numbers, you probably memorized the multiplication table. In effect, you memorized 100 specific solutions. That kind of knowledge is not algorithmic.
344 | >要理解算法是什么,先从一些不是算法的内容来开始也许会有所帮助。当你学个位数字乘法的时候,你可能要背下来整个乘法表。实际上你记住了100个特定的算式。这种知识就不是算法。
345 |
346 | But if you were “lazy”, you might have learned a few tricks. For example, to find the product of n and 9, you can write n−1 as the first digit and 10−n as the second digit. This trick is a general solution for multiplying any single-digit number by 9. That’s an algorithm!
347 | >但如果你很『懒』,你就可能会有一些小技巧。比如找到一个n与9的成绩,你可以把n-1写成第一位,10-n携程第二位。这个技巧是应对任何个位数字乘以9的算式。这就是一个算法了!
348 |
349 |
350 | Similarly, the techniques you learned for addition with carrying, subtraction with borrowing, and long division are all algorithms. One of the characteristics of algorithms is that they do not require any intelligence to carry out. They are mechanical processes where each step follows from the last according to a simple set of rules.
351 | >相似地,你学过的进位的加法,借位的减法,以及长除法,都是算法。这些算法的一个共同特点就是不需要任何智力就能进行。它们都是机械的过程,每一步都跟随上一步,遵循着很简单的一套规则。
352 |
353 |
354 | Executing algorithms is boring, but designing them is interesting, intellectually challenging, and a central part of computer science.
355 | >执行算法是很无聊的,但设计算法很有趣,是智力上的一种挑战,也是计算机科学的核心部分。
356 |
357 | Some of the things that people do naturally, without difficulty or conscious thought, are the hardest to express algorithmically. Understanding natural language is a good example. We all do it, but so far no one has been able to explain how we do it, at least not in the form of an algorithm.
358 | >有的事情人们平时做起来很简单,甚至都不用思考,这些事情往往最难用算法来表达。比如理解自然语言就是个例子。我们都能理解自然语言,但目前为止还没有人能解释我们到底是怎么做到的,至少没有人把这个过程归纳出算法的形式。
359 |
360 |
361 | ##7.7 Debugging 调试
362 |
363 | As you start writing bigger programs, you might find yourself spending more time debugging. More code means more chances to make an error and more places for bugs to hide.
364 | >现在你已经开始写一些比较大的程序了,你可能发现自己比原来花更多时间来调试了。代码越多,也就意味着出错的可能也越大了,bug也有了更多的藏身之处了。
365 |
366 |
367 | One way to cut your debugging time is “debugging by bisection”. For example, if there are 100 lines in your program and you check them one at a time, it would take 100 steps. Instead, try to break the problem in half. Look at the middle of the program, or near it, for an intermediate value you can check. Add a print statement (or something else that has a verifiable effect) and run the program.
368 | >『对折调试』是一种节省调试时间的方法。比如,如果你的程序有100行,你检查一遍就要大概100步了。而对折方法就是把程序分成两半。看程序中间位置,或者靠近中间位置的,检查一些中间值。在这些位置添加一些print语句(或者其他能够能起到验证效果的东西),然后运行程序。
369 |
370 |
371 | If the mid-point check is incorrect, there must be a problem in the first half of the program. If it is correct, the problem is in the second half.
372 | >如果中间点检查出错了,那必然是程序的前半部分有问题。如果中间点没调试,那问题就是在后半段了。
373 |
374 |
375 | Every time you perform a check like this, you halve the number of lines you have to search. After six steps (which is fewer than 100), you would be down to one or two lines of code, at least in theory.
376 | >每次你都这样检查,你就让你要检查的代码数量减半了。一般六步之后(远小于100次了),理论上你就差不多已经到代码的末尾一两行了。
377 |
378 | In practice it is not always clear what the “middle of the program” is and not always possible to check it. It doesn’t make sense to count lines and find the exact midpoint. Instead, think about places in the program where there might be errors and places where it is easy to put a check. Then choose a spot where you think the chances are about the same that the bug is before or after the check.
379 | >在实际操作当中,程序中间位置并不是总那么明确,也未必就很容易去检查。所以不用数行数来找确定的中间点。相反的,只要考虑一下程序中哪些地方容易调试,然后哪些地方进行检验比较容易就行了。然后你就在你考虑好的位置检验一下看看bug是在那个位置之前还是之后。
380 |
381 | ##7.8 Glossary 术语列表
382 |
383 | reassignment:
384 | Assigning a new value to a variable that already exists.
385 | >再赋值:对一个已经存在的有值变量赋予一个新的值。
386 |
387 | update:
388 | An assignment where the new value of the variable depends on the old.
389 | >更新:根据一个变量的旧值,进行一定的修改,再赋值给这个变量。
390 |
391 |
392 | initialization:
393 | An assignment that gives an initial value to a variable that will be updated.
394 | >初始化:给一个变量初始值,以便于后续进行更新。
395 |
396 | increment:
397 | An update that increases the value of a variable (often by one).
398 | >递增:每次给一个变量增加一定的值(一般是加1)
399 |
400 | decrement:
401 | An update that decreases the value of a variable.
402 | >递减:每次给一个变量减去一定的值。
403 |
404 | iteration:
405 | Repeated execution of a set of statements using either a recursive function call or a loop.
406 | >迭代:重复执行一系列语句,使用递归函数调用的方式,或者循环的方式。
407 |
408 | infinite loop:
409 | A loop in which the terminating condition is never satisfied.
410 | >无限循环:终止条件永远无法满足的循环。
411 |
412 | algorithm:
413 | A general process for solving a category of problems.
414 | >算法:解决某一类问题的一系列通用的步骤。
415 |
416 | ##7.9 Exercises 练习
417 | ###Exercise 1 练习1
418 |
419 | Copy the loop from Section 7.5 and encapsulate it in a function called mysqrt that takes a as a parameter, chooses a reasonable value of x, and returns an estimate of the square root of a.
420 | >从7.5复制一个循环,然后改写成名字叫做mysqrt的函数,该函数用一个a作为参数,选择一个适当的起始值x,然后返回a的平方根的近似值。
421 |
422 | To test it, write a function named test_square_root that prints a table like this:
423 | >测试这个函数,写一个叫做test_suqare_root的函数来输出以下这样的表格:
424 |
425 | | a |mysqrt(a)|math.sqrt(a)|diff |
426 | |--------|--------|--------|--------|
427 | |1.0 |1.0 | 1.0 | 0.0|
428 | |2.0| 1.41421356237| 1.41421356237| 2.22044604925e-16|
429 | |3.0| 1.73205080757| 1.73205080757| 0.0|
430 | |4.0| 2.0 | 2.0 | 0.0|
431 | |5.0| 2.2360679775 | 2.2360679775 | 0.0|
432 | |6.0| 2.44948974278| 2.44948974278| 0.0|
433 | |7.0| 2.64575131106 |2.64575131106 |0.0|
434 | |8.0| 2.82842712475| 2.82842712475| 4.4408920985e-16|
435 | |9.0| 3.0 | 3.0 | 0.0|
436 | | | | | |
437 |
438 | The first column is a number, a; the second column is the square root of acomputed with mysqrt; the third column is the square root computed by math.sqrt; the fourth column is the absolute value of the difference between the two estimates.
439 | >第一列是数a;第二列是咱们自己写的函数mysqrt计算出来的平方根,第三行是用Python内置的math.sqrt函数计算的平方根,最后一行是这两者的差值的绝对值。
440 |
441 |
442 | ###Exercise 2 练习2
443 |
444 | The built-in function eval takes a string and evaluates it using the Python interpreter. For example:
445 | >Python的内置函数eval接收字符串作为参数,然后用Python的解释器来运行。例如:
446 |
447 | ```Python
448 | >>> eval('1 + 2 * 3')
449 | 7
450 | >>> import math
451 | >>> eval('math.sqrt(5)')
452 | 2.2360679774997898
453 | >>> eval('type(math.pi)')
454 |
455 | ```
456 |
457 | Write a function called eval_loop that iteratively prompts the user, takes the resulting input and evaluates it using eval, and prints the result.
458 | >写一个叫做eval_loop的函数,交互地提醒用户,获取输入,然后用eval对输入进行运算,把结果打印出来。
459 |
460 |
461 | It should continue until the user enters 'done', and then return the value of the last expression it evaluated.
462 | >这个程序要一直运行,直到用户输入『done』才停止,然后输出最后一次计算的表达式的值。
463 |
464 |
465 | ##Exercise 3 练习3
466 |
467 | The mathematician Srinivasa Ramanujan found an infinite series that can be used to generate a numerical approximation of 1 / π:
468 | >传奇的数学家拉马努金发现了一个无穷级数(1914年的论文),能够用来计算圆周率倒数的近似值:
469 |
470 | $$\frac{1}{\pi}=\frac{2\sqrt{2}}{99^2}\sum_{k=0}^\infty\frac{(4k)!(26390k+1103)}{(k!)^4396^{4k}}$$
471 |
472 | (译者注:这位拉马努金是一位非常杰出的数学家,自学成才,以数论为主要研究内容,可惜33岁的时候就英年早逝。他被哈代誉为超越希尔伯特的天才。)
473 |
474 | Write a function called estimate_pi that uses this formula to compute and return an estimate of π. It should use a while loop to compute terms of the summation until the last term is smaller than 1e-15 (which is Python notation for 10−15). You can check the result by comparing it to math.pi.
475 | [Solution](http://thinkpython2.com/code/pi.py)
476 | >写一个名叫estimate_pi的函数,用上面这个方程来计算并返回一个圆周率π的近似值。要使用一个while循环来计算出总和的每一位,最后一位要小于10的-15次方。你可以对比一下计算结果和Python内置的math.pi。
477 | >[样例代码](http://thinkpython2.com/code/pi.py)
478 |
479 |
--------------------------------------------------------------------------------
/ThinkPython-8.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 8
2 | Date: 2015-11-29
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | # Chapter 8 Strings 字符串
7 |
8 | Strings are not like integers, floats, and booleans. A string is a sequence, which means it is an ordered collection of other values. In this chapter you’ll see how to access the characters that make up a string, and you’ll learn about some of the methods strings provide.
9 |
10 | > 字符串和整形、浮点数以及布尔值很不一样。一个字符串是一个序列,意味着是对其他值的有序排列。在本章你将学到如何读取字符串中的字符,你还会学到一些字符串相关的方法。
11 |
12 | ## 8.1 A string is a sequence 字符串是序列
13 |
14 | A string is a sequence of characters. You can access the characters one at a time with the bracket operator:
15 |
16 | > 字符串就是一串有序的字符。你可以通过方括号操作符,每次去访问字符串中的一个字符:
17 |
18 | ```Python
19 | >>> fruit = 'banana'
20 | >>> letter = fruit[1]
21 | ```
22 |
23 | The second statement selects character number 1 from fruit and assigns it to letter.
24 |
25 | > 第二个语句选择了 fruit 这个字符串的序号为1的字符,并把这个字符赋值给了 letter 这个变量。
26 | > (译者注:思考一下这里的 letter 是一个什么类型的变量。)
27 |
28 | The expression in brackets is called an index. The index indicates which character in the sequence you want \(hence the name\).
29 | But you might not get what you expect:
30 |
31 | > 方括号内的内容叫做索引。索引指示了你所指定的字符串中字符的位置(就跟名字差不多)。
32 | > 但你可能发现得到的结果和你预期的有点不一样:
33 |
34 | ```Python
35 | >>> letter
36 | 'a'
37 | ```
38 |
39 | For most people, the first letter of 'banana' is b, not a. But for computer scientists, the index is an offset from the beginning of the string, and the offset of the first letter is zero.
40 |
41 | > 大多数人都认为banana 的第『1』个字符应该是 b,而不是 a。但对于计算机科学家来说,索引是字符串从头的偏移量,所以真正的首字母偏移量应该是0.
42 |
43 | ```Python
44 | >>> letter = fruit[0]
45 | >>> letter
46 | 'b'
47 | ```
48 |
49 | So b is the 0th letter \(“zero-eth”\) of 'banana', a is the 1th letter \(“one-eth”\), and n is the 2th letter \(“two-eth”\).
50 |
51 | > 所以 b 就是字符串 banana 的第『0』个字符,而 a 是第『1』个,n 就是第『2』个了。
52 |
53 | As an index you can use an expression that contains variables and operators:
54 |
55 | > 你可以在方括号内的索引中使用变量和表达式:
56 |
57 | ```Python
58 | >>> i = 1
59 | >>> fruit[i]
60 | 'a'
61 | >>> fruit[i+1]
62 | 'n'
63 | ```
64 |
65 | But the value of the index has to be an integer. Otherwise you get:
66 |
67 | > 但要注意的事,索引的值必须是整形的。否则你就会遇到类型错误了:
68 |
69 | ```Python
70 | >>> letter = fruit[1.5]
71 | TypeError: string indices must be integers
72 | ```
73 |
74 | ## 8.2 len 长度
75 |
76 | len is a built-in function that returns the number of characters in a string:
77 |
78 | > len 是一个内置函数,会返回一个字符串中字符的长度:
79 |
80 | ```Python
81 | >>> fruit = 'banana'
82 | >>> len(fruit) 6
83 | ```
84 |
85 | To get the last letter of a string, you might be tempted to try something like this:
86 |
87 | > 要得到一个字符串的最后一个字符,你可能会想到去利用 len 函数:
88 |
89 | ```Python
90 | >>> length = len(fruit)
91 | >>> last = fruit[length]
92 | IndexError: string index out of range
93 | ```
94 |
95 | The reason for the IndexError is that there is no letter in ’banana’ with the index 6. Since we started counting at zero, the six letters are numbered 0 to 5. To get the last character, you have to subtract 1 from length:
96 |
97 | > 出现索引错误的原因就是banana 这个字符串在第『6』个位置是没有字母的。因为我们从0开始数,所以这一共6个字母的顺序是0到5号。因此要得到最后一次字符,你需要在字符串长度的基础上减去1才行:
98 |
99 | ```Python
100 | >>> last = fruit[length-1]
101 | >>> last
102 | 'a'
103 | ```
104 |
105 | Or you can use negative indices, which count backward from the end of the string. The expression fruit\[-1\] yields the last letter, fruit\[-2\] yields the second to last, and so on.
106 |
107 | > 或者你也可以用负数索引,意思就是从字符串的末尾向前数几位。fruit\[-1\]这个表达式给你最后一个字符,fruit\[-2\]给出倒数第二个,依此类推。
108 |
109 | ## 8.3 Traversal with a for loop 用 for 循环进行遍历
110 |
111 | A lot of computations involve processing a string one character at a time. Often they start at the beginning, select each character in turn, do something to it, and continue until the end. This pattern of processing is called a traversal. One way to write a traversal is with a while loop:
112 |
113 | > 很多计算过程都需要每次从一个字符串中拿一个字符。一般都是从头开始,依次得到每个字符,然后做点处理,然后一直到末尾。这种处理模式叫遍历。写一个遍历可以使用 while 循环:
114 |
115 | ```Python
116 | index = 0
117 | while index < len(fruit):
118 | letter = fruit[index]
119 | print(letter)
120 | index = index + 1
121 | ```
122 |
123 | This loop traverses the string and displays each letter on a line by itself. The loop condition is index < len\(fruit\), so when index is equal to the length of the string, the condition is false, and the body of the loop doesn’t run. The last character accessed is the one with the index len\(fruit\)-1, which is the last character in the string.
124 |
125 | > 这个循环遍历了整个字符串,然后它再把买一个字符显示在一行上面。循环条件是 index 这个变量小于字符串 fruit 的长度,所以当 index 与字符串长度相等的时候,条件就不成立了,循环体就不运行了。最后一个字符被获取的时候,index 正好是len\(fruit\)-1,这就已经是该字符串的最后一个字符了。
126 |
127 | As an exercise, write a function that takes a string as an argument and displays the letters backward, one per line.
128 |
129 | > 下面就练习一下了,写一个函数,接收一个字符串做参数,然后倒序显示每一个字符,每行显示一个。
130 |
131 | Another way to write a traversal is with a for loop:
132 |
133 | > 另外一种遍历的方法就是 for 循环了:
134 |
135 | ```Python
136 | for letter in fruit:
137 | print(letter)
138 | ```
139 |
140 | Each time through the loop, the next character in the string is assigned to the variable letter. The loop continues until no characters are left.
141 |
142 | > 每次循环之后,字符串中的下一个字符都会赋值给变量 letter。循环在进行到没有字符剩余的时候就停止了。
143 |
144 | The following example shows how to use concatenation \(string addition\) and a for loop to generate an abecedarian series \(that is, in alphabetical order\).
145 |
146 | > 下面的例子展示了如何使用级联(字符串加法)以及一个 for 循环来生成一个简单的序列(用字母表顺序)。
147 |
148 | In Robert McCloskey’s book Make Way for Ducklings, the names of the ducklings are Jack, Kack, Lack, Mack, Nack, Ouack, Pack, and Quack. This loop outputs these names in order:
149 |
150 | > 在 Robert McCloskey 的一本名叫《Make Way for Ducklings》的书中,小鸭子的名字依次为:Jack, Kack, Lack, Mack, Nack, Ouack, Pack, 和Quack。下面这个循环会依次输出他们的名字:
151 |
152 | ```Python
153 | prefixes = 'JKLMNOPQ'
154 | suffix = 'ack'
155 | for letter in prefixes:
156 | print(letter + suffix)
157 | ```
158 |
159 | The output is:
160 |
161 | > 输出结果如下:
162 |
163 | ```Python
164 | Jack Kack Lack Mack Nack Oack Pack Qack
165 | ```
166 |
167 | Of course, that’s not quite right because “Ouack” and “Quack” are misspelled. As an exercise, modify the program to fix this error.
168 |
169 | > 当然了,有点不准确的地方,因为有“Ouack”和 “Quack”两处拼写错了。做个练习,修改一下程序,改正这个错误。
170 |
171 | ## 8.4 String slices 字符串切片
172 |
173 | A segment of a string is called a slice. Selecting a slice is similar to selecting a character:
174 |
175 | > 字符串的一段叫做切片。从字符串中选择一部分做切片,与选择一个字符有些相似:
176 |
177 | ```Python
178 | >>> s = 'Monty Python'
179 | >>> s[0:5]
180 | 'Monty'
181 | >>> s[6:12]
182 | 'Python'
183 | ```
184 |
185 | The operator \[n:m\] returns the part of the string from the “n-eth” character to the “m-eth” character, including the first but excluding the last. This behavior is counter intuitive, but it might help to imagine the indices pointing between the characters, as in Figure 8.1.
186 |
187 | > \[n:m\]这种操作符,会返回字符串中从第『n』个到第『m』个的字符,包含开头的第『n』个,但不包含末尾的第『m』个。这个设计可能有点违背直觉,但可能有助于想象这个切片在字符串中的方向,如图8.1。
188 | >
189 | > ---
190 | >
191 | > 
192 |
193 | Figure 8.1: Slice indices.
194 |
195 | ---
196 |
197 | If you omit the first index \(before the colon\), the slice starts at the beginning of the string. If you omit the second index, the slice goes to the end of the string:
198 |
199 | > 如果你忽略了第一个索引(就是冒号前面的那个),切片会默认从字符串头部开始。如果你忽略了第二个索引,切片会一直包含到最后一位:
200 |
201 | ```Python
202 | >>> fruit = 'banana'
203 | >>> fruit[:3]
204 | 'ban'
205 | >>> fruit[3:]
206 | 'ana'
207 | ```
208 |
209 | If the first index is greater than or equal to the second the result is an empty string, represented by two quotation marks:
210 |
211 | > 如果两个索引相等,得到的就是空字符串了,用两个单引号来表示:
212 |
213 | ```Python
214 | >>> fruit = 'banana'
215 | >>> fruit[3:3]
216 | ''
217 | ```
218 |
219 | An empty string contains no characters and has length 0, but other than that, it is the same as any other string.
220 | Continuing this example, what do you think fruit\[:\] means? Try it and see.
221 |
222 | > 空字符串不包含字符,长度为0,除此之外,都与其他字符串是一样的。
223 | > 那么来练习一下,你觉得 fruit\[:\]这个是什么意思?在程序中试试吧。
224 |
225 | ## 8.5 Strings are immutable 字符串不可修改
226 |
227 | It is tempting to use the \[\] operator on the left side of an assignment, with the intention of changing a character in a string. For example:
228 |
229 | > 大家总是有可能想试试把方括号在赋值表达式的等号左侧,试图去更改字符串中的某一个字符。比如:
230 |
231 | ```Python
232 | >>> greeting = 'Hello, world!'
233 | >>> greeting[0] = 'J'
234 | TypeError: 'str' object does not support item assignment
235 | ```
236 |
237 | The “object” in this case is the string and the “item” is the character you tried to assign. For now, an object is the same thing as a value, but we will refine that definition later \(Section 10.10\).
238 |
239 | > 『object』是对象的意思,这里指的是字符串类 string,然后『item』是指你试图赋值的字符串中的字符。目前来说,一个对象就跟一个值差不多,但后续在第十章第十节我们再对这个定义进行详细讨论。
240 |
241 | The reason for the error is that strings are immutable, which means you can’t change an existing string. The best you can do is create a new string that is a variation on the original:
242 |
243 | > 产生上述错误的原因是字符串是不能被修改的,这意味着你不能对一个已经存在的字符串进行任何改动。你顶多也就能建立一个新字符串,新字符串可以基于旧字符串进行一些改动。
244 |
245 | ```Python
246 | >>> greeting = 'Hello, world!'
247 | >>> new_greeting = 'J' + greeting[1:]
248 | >>> new_greeting
249 | 'Jello, world!'
250 | ```
251 |
252 | This example concatenates a new first letter onto a slice of greeting. It has no effect on the original string.
253 |
254 | > 上面的例子中,对 greeting 这个字符串进行了切片,然后添加了一个新的首字母过去。这并不会对原始字符串有任何影响。(译者注:也就是 greeting 这个字符串的值依然是原来的值,是不可改变的。)
255 |
256 | ## 8.6 Searching 搜索
257 |
258 | What does the following function do?
259 |
260 | > 下面这个函数是干啥的?
261 |
262 | ```Python
263 | def find(word, letter):
264 | index = 0
265 | while index < len(word):
266 | if word[index] == letter:
267 | return index
268 | index = index + 1
269 | return -1
270 | ```
271 |
272 |
273 | ```Python
274 | # 改进的find函数,利用列表收集字母letter在单词word中出现的全部位置.
275 | def find(word, letter):
276 | index = 0
277 |
278 | result_list=[]
279 |
280 | while index < len(word):
281 | if word[index] == letter:
282 |
283 | result_list.append(index)
284 |
285 | index = index + 1
286 |
287 | return result_list
288 |
289 | find('banana','a')
290 | ```
291 |
292 |
293 | In a sense, find is the inverse of the \[\] operator. Instead of taking an index and extracting the corresponding character, it takes a character and finds the index where that character appears. If the character is not found, the function returns -1.
294 |
295 | > 简单来说,find 函数,也就是查找,是方括号操作符\[\]的逆运算。方括号是之道索引然后提取对应的字符,而查找函数是选定一个字符去查找这个字符出现的索引位置。如果字符没有被报道,函数就返回-1。
296 |
297 | This is the first example we have seen of a return statement inside a loop. If word\[index\] == letter, the function breaks out of the loop and returns immediately.
298 | If the character doesn’t appear in the string, the program exits the loop normally and returns -1.
299 |
300 | > 这是我们见过的第一个返回语句位于循环体内的例子。如果word\[index\]等于letter,函数就跳出循环立刻返回。如果字符在字符串里面没出现,程序正常退出循环并且返回-1。
301 |
302 | This pattern of computation—traversing a sequence and returning when we find what we are looking for—is called a search.
303 | As an exercise, modify find so that it has a third parameter, the index in word where it should start looking.
304 |
305 | > 这种计算-遍历一个序列然后返回我们要找的东西的模式就叫做搜索了。
306 | > 做个练习,修改一下 find 函数,加入第三个参数,这个参数为查找开始的字符串位置。
307 |
308 | ## 8.7 Looping and counting 循环和计数
309 |
310 | The following program counts the number of times the letter a appears in a string:
311 |
312 | > 下面这个程序计算了字母 a 在一个字符串中出现的次数:
313 |
314 | ```Python
315 | word = 'banana'
316 | count = 0
317 | for letter in word:
318 | if letter == 'a':
319 | count = count + 1
320 | print(count)
321 | ```
322 |
323 | This program demonstrates another pattern of computation called a counter. The variable count is initialized to 0 and then incremented each time an a is found. When the loop exits, count contains the result—the total number of a’s.
324 |
325 | > 这一程序展示了另外一种计算模式,叫做计数。变量 count 被初始化为0,然后每次在字符串中找到一个 a,就让 count 加1.当循环退出的时候,count 就包含了 a 出现的总次数。
326 |
327 | As an exercise, encapsulate this code in a function named count, and generalize it so that it accepts the string and the letter as arguments.
328 | Then rewrite the function so that instead of traversing the string, it uses the three-parameter version of find from the previous section.
329 |
330 | > 做个练习,把上面的代码封装进一个名叫 count 的函数中,泛化一下,一遍让他接收任何字符串和字幕作为参数。
331 | > 然后再重写一下这个函数,这次不再让它遍历整个字符串,而使用上一节中练习的三参数版本的 find 函数。
332 |
333 | ## 8.8 String methods 字符串方法
334 |
335 | Strings provide methods that perform a variety of useful operations. A method is similar to a function—it takes arguments and returns a value—but the syntax is different. For example, the method upper takes a string and returns a new string with all uppercase letters.
336 | Instead of the function syntax upper\(word\), it uses the method syntax word.upper\(\).
337 |
338 | > 字符串提供了一些方法,这些方法能够进行很多有用的操作。方法和函数有些类似,也接收参数然后返回一个值,但语法稍微不同。比如,upper 这个方法就读取一个字符串,返回一个全部为大写字母的新字符串。
339 | > 与函数的 upper\(word\)语法不同,方法的语法是 word.upper\(\)。
340 |
341 | ```Python
342 | >>> word = 'banana'
343 | >>> new_word = word.upper()
344 | >>> new_word 'BANANA'
345 | ```
346 |
347 | This form of dot notation specifies the name of the method, upper, and the name of the string to apply the method to, word. The empty parentheses indicate that this method takes no arguments.
348 |
349 | > 这种用点号分隔的方法表明了使用的方法名字为 upper,使用这个方法的字符串的名字为 word。后面括号里面是空白的,表示这个方法不接收参数。
350 |
351 | A method call is called an invocation; in this case, we would say that we are invoking upper on word.
352 |
353 | > 方法的调用被叫做——调用(译者注:这真是扯淡,中文都混淆成调用,英文里面 invocation 和 invoke 都有祈祷的意思,和 call 有显著的意义差别,但中文都混淆成调用,这种例子不胜枚举,所以大家尽量多读原版作品。);在这里,我们就说调用了 word 的 upper 方法。
354 |
355 | As it turns out, there is a string method named find that is remarkably similar to the function we wrote:
356 |
357 | > 结果我们发现string 有一个方法叫做 find,跟我们写过的函数 find 有惊人的相似:
358 |
359 | ```Python
360 | >>> word = 'banana'
361 | >>> index = word.find('a')
362 | >>> index
363 | 1
364 | ```
365 |
366 | In this example, we invoke find on word and pass the letter we are looking for as a parameter.
367 |
368 | > 在这里我们调用了 word 的 find 方法,然后给定了我们要找的字母 a 作为一个参数。
369 |
370 | Actually, the find method is more general than our function; it can find substrings, not just characters:
371 |
372 | > 实际上,这个 find 方法比我们的 find 函数功能更通用;它不仅能查找字符,还能查找字符串:
373 |
374 | ```Python
375 | >>> word.find('na')
376 | 2
377 | ```
378 |
379 | By default, find starts at the beginning of the string, but it can take a second argument, the index where it should start:
380 |
381 | > 默认情况下 find 方法从字符串的开头来查找,不过可以给它一个第二个参数,让它从指定位置查找:
382 |
383 | ```Python
384 | >>> word.find('na', 3)
385 | 4
386 | ```
387 |
388 | This is an example of an optional argument; find can also take a third argument, the index where it should stop:
389 |
390 | > 这是一个可选参数的例子;find 方法还能接收第三个参数,可以指定查找终止的位置:
391 |
392 | ```Python
393 | >>> name = 'bob'
394 | >>> name.find('b', 1, 2)
395 | -1
396 | ```
397 |
398 | This search fails because b does not appear in the index range from 1 to 2, not including 2. Searching up to, but not including, the second index makes find consistent with the slice operator.
399 |
400 | > 这个搜索失败了,因为 b 并没有在索引1到2且不包括2的字符中间出现。搜索到指定的第三个变量作为索引的位置,但不包括该位置,这就让 find 方法与切片操作符相一致。
401 |
402 | ## 8.9 The in operator 运算符 in
403 |
404 | The word in is a boolean operator that takes two strings and returns True if the first appears as a substring in the second:
405 |
406 | > in 这个词在字符串操作中是一个布尔操作符,它读取两个字符串,如果前者的字符串为后者所包含,就返回真,否则为假:
407 |
408 | ```Python
409 | >>> 'a' in 'banana'
410 | True
411 | >>> 'seed' in 'banana'
412 | False
413 | ```
414 |
415 | For example, the following function prints all the letters from word1 that also appear in word2:
416 |
417 | > 举个例子,下面的函数显示所有同时在 word1和 word2当中出现的字母:
418 |
419 | ```Python
420 | def in_both(word1, word2):
421 | for letter in word1:
422 | if letter in word2:
423 | print(letter)
424 | ```
425 |
426 | With well-chosen variable names, Python sometimes reads like English. You could read this loop, “for \(each\) letter in \(the first\) word, if \(the\) letter \(appears\) in \(the second\) word, print \(the\) letter.”
427 | Here’s what you get if you compare apples and oranges:
428 |
429 | > 选好变量名的话,Python 有时候读起来就跟英语差不多。你读一下这个循环,就能发现,『对第一个 word 当中的每一个字母letter,如果这个字母也在第二个 word 当中出现,就输出这个字母 letter。』
430 |
431 | ```Python
432 | >>> in_both('apples', 'oranges')
433 | a e s
434 | ```
435 |
436 | ## 8.10 String comparison 字符串对比
437 |
438 | The relational operators work on strings. To see if two strings are equal:
439 |
440 | > 关系运算符对于字符串来说也可用。比如可以看看两个字符串是不是相等:
441 |
442 | ```Python
443 | if word == 'banana':
444 | print('All right, bananas.')
445 | ```
446 |
447 | Other relational operations are useful for putting words in alphabetical order:
448 |
449 | > 其他的关系运算符可以来把字符串按照字母表顺序排列:
450 |
451 | ```Python
452 | if word < 'banana':
453 | print('Your word, ' + word + ', comes before banana.')
454 | elif word > 'banana':
455 | print('Your word, ' + word + ', comes after banana.')
456 | else:
457 | print('All right, bananas.')
458 | ```
459 |
460 | Python does not handle uppercase and lowercase letters the same way people do. All the uppercase letters come before all the lowercase letters, so:
461 | Your word, Pineapple, comes before banana.
462 |
463 | > Python 对大小写字母的处理与人类常规思路不同。所有大写字母都在小写字母之前,所以顺序上应该是:
464 | > Your word,然后是 Pineapple,然后才是 banana。
465 |
466 | A common way to address this problem is to convert strings to a standard format, such as all lowercase, before performing the comparison. Keep that in mind in case you have to defend yourself against a man armed with a Pineapple.
467 |
468 | > 一个解决这个问题的普遍方法是把字符串转换为标准格式,比如都转成小写的,然后再进行比较。一定要记得哈,以免你遇到一个用 Pineapple 武装着自己的家伙的时候手足无措。
469 |
470 | ## 8.11 Debugging 调试
471 |
472 | When you use indices to traverse the values in a sequence, it is tricky to get the beginning and end of the traversal right. Here is a function that is supposed to compare two words and return True if one of the words is the reverse of the other, but it contains two errors:
473 |
474 | > 使用索引来遍历一个序列中的值的时候,弄清楚遍历的开头和结尾很不容易。下面这个函数用来对比两个单词,如果一个是另一个的倒序就返回真,但这个函数代码中有两处错误:
475 |
476 | ```Python
477 | def is_reverse(word1, word2):
478 | if len(word1) != len(word2):
479 | return False
480 | i = 0
481 | j = len(word2)
482 | while j > 0:
483 | if word1[i] != word2[j]:
484 | return False
485 | i = i+1
486 | j = j-1
487 | return True
488 | ```
489 |
490 | The first if statement checks whether the words are the same length. If not, we can return False immediately. Otherwise, for the rest of the function, we can assume that the words are the same length. This is an example of the guardian pattern in Section 6.8.
491 |
492 | > 第一个 if 语句是检查两个词的长度是否一样。如果不一样长,当场就返回假。对函数其余部分,我们假设两个单词一样长。这里用到了守卫模式,在第6章第8节我们提到过。
493 |
494 | i and j are indices: i traverses word1 forward while j traverses word2 backward. If we find two letters that don’t match, we can return False immediately. If we get through the whole loop and all the letters match, we return True.
495 | If we test this function with the words “pots” and “stop”, we expect the return value True, but we get an IndexError:
496 |
497 | > i 和 j 都是索引:i 从头到尾遍历单词 word1,而 j 逆向遍历单词word2.如果我们发现两个字母不匹配,就可以立即返回假。如果经过整个循环,所有字母都匹配,就返回真。
498 | > 如果我们用这个函数来处理单词『pots』和『stop』,我们希望函数返回真,但得到的却是索引错误:
499 |
500 | ```Python
501 | >>> is_reverse('pots', 'stop')
502 | ... File "reverse.py", line 15, in is_reverse if word1[i] != word2[j]: IndexError: string index out of range
503 | ```
504 |
505 | For debugging this kind of error, my first move is to print the values of the indices immediately before the line where the error appears.
506 |
507 | > 为了改正这个错误,第一步就是在出错的那行之前先输出索引的值。
508 |
509 | ```Python
510 | while j > 0:
511 | print(i, j) # print here
512 | if word1[i] != word2[j]:
513 | return False
514 | i = i+1
515 | j = j-1
516 | ```
517 |
518 | Now when I run the program again, I get more information:
519 |
520 | > 然后我再次运行函数,得到更多信息了:
521 |
522 | ```Python
523 | >>> is_reverse('pots', 'stop')
524 | 0 4
525 | ... IndexError: string index out of range
526 | ```
527 |
528 | The first time through the loop, the value of j is 4, which is out of range for the string 'pots'. The index of the last character is 3, so the initial value for j should be len\(word2\)-1.
529 | If I fix that error and run the program again, I get:
530 |
531 | > 第一次循环完毕的时候,j 的值是4,这超出了『pots』这个字符串的范围了(译者注:应该是0-3)。最后一个索引应该是3,所以 j 的初始值应该是 len\(word2\)-1。
532 |
533 | ```Python
534 | >>> is_reverse('pots', 'stop')
535 | 0 3 1 2 2 1
536 | True
537 | ```
538 |
539 | This time we get the right answer, but it looks like the loop only ran three times, which is suspicious. To get a better idea of what is happening, it is useful to draw a state diagram. During the first iteration, the frame for is\_reverse is shown in Figure 8.2.
540 |
541 | > 这次我们得到了正确的结果,但似乎循环只走了三次,这有点奇怪。为了弄明白带到怎么回事,我们可以画一个状态图。在第一次迭代的过程中,is\_reverse 的框架如图8.2所示。
542 | >
543 | > ---
544 | >
545 | > 
546 | > Figure 8.2: State diagram.
547 | >
548 | > ---
549 | >
550 | > I took some license by arranging the variables in the frame and adding dotted lines to show that the values of i and j indicate characters in word1and word2.
551 | > Starting with this diagram, run the program on paper, changing the values ofi and j during each iteration. Find and fix the second error in this function.
552 | > 我通过设置变量框架中添加虚线表明,i和j的值显示在人物word1and word2拿许可证。
553 | > 从这个图上运行的程序,文件,更改这些值I和J在每一次迭代过程。发现并解决此函数中的二次错误。
554 |
555 | ## 8.12 Glossary 术语列表
556 |
557 | object:
558 | Something a variable can refer to. For now, you can use “object” and “value” interchangeably.
559 |
560 | > 对象:一个值能够指代的东西。目前为止,你可以把对象和值暂且作为一码事来理解。
561 |
562 | sequence:
563 | An ordered collection of values where each value is identified by an integer index.
564 |
565 | > 序列:一系列值的有序排列,每一个值都有一个唯一的整数序号。
566 |
567 | item:
568 | One of the values in a sequence.
569 |
570 | > 元素:一列数值序列当中的一个值。
571 |
572 | index:
573 | An integer value used to select an item in a sequence, such as a character in a string. In Python indices start from 0.
574 |
575 | > 索引:一个整数值,用来指代一个序列中的特定一个元素,比如在字符串里面就指代一个字符。在 Python 里面索引从0开始计数。
576 |
577 | slice:
578 | A part of a string specified by a range of indices.
579 |
580 | > 切片:字符串的一部分,通过一个索引区间来取得。
581 |
582 | empty string:
583 | A string with no characters and length 0, represented by two quotation marks.
584 |
585 | > 空字符串:没有字符的字符串,长度为0,用两个单引号表示。
586 |
587 | immutable:
588 | The property of a sequence whose items cannot be changed.
589 |
590 | > 不可更改:一个序列中所有元素不能被改变的性质。
591 |
592 | traverse:
593 | To iterate through the items in a sequence, performing a similar operation on each.
594 |
595 | > 遍历:在一个序列中依次对每一个元素进行某种相似运算的过程。
596 |
597 | search:
598 | A pattern of traversal that stops when it finds what it is looking for.
599 |
600 | > 搜索:一种遍历的模式,找到要找的内容的时候就停止。
601 |
602 | counter:
603 | A variable used to count something, usually initialized to zero and then incremented.
604 |
605 | > 计数:一种用来统计某种东西数量的变量,一般初始化为0,然后逐次递增。
606 |
607 | invocation:
608 | A statement that calls a method.
609 |
610 | > 方法调用:调用方法的语句。
611 |
612 | optional argument:
613 | A function or method argument that is not required.
614 |
615 | > 可选参数:一个函数或者方法中有一些参数是可选的,非必需的。
616 |
617 | ## 8.13 Exercises 练习
618 |
619 | ### Exercise 1 练习1
620 |
621 | Read the documentation of the string methods at [here](http://docs.python.org/2/library/stdtypes.html#string-methods). You might want to experiment with some of them to make sure you understand how they work. strip and replace are particularly useful.
622 |
623 | > 阅读 [这里](http://docs.python.org/2/library/stdtypes.html#string-methods)关于字符串的文档。你也许会想要试试其中一些方法,来确保你理解它们的意义。比如 strip 和 replace 都特别有用。
624 |
625 | The documentation uses a syntax that might be confusing. For example, in find\(sub\[, start\[, end\]\]\), the brackets indicate optional arguments. So sub is required, but start is optional, and if you include start, then end is optional.
626 |
627 | > 文档的语法有可能不太好理解。比如在find 这个方法中,方括号表示了可选参数。所以 sub 是必须的参数,但 start 是可选的,如果你包含了 start,end 就是可选的了。
628 |
629 | ### Exercise 2 练习2
630 |
631 | There is a string method called count that is similar to the function in Section 8.7. Read the documentation of this method and write an invocation that counts the number of 'a's in 'banana'.
632 |
633 | > 字符串有个方法叫 count,与咱们在8.7中写的 count 函数很相似。 阅读一下这个方法的文档,然后写一个调用这个方法的代码,统计一下 banana 这个单词中 a 出现的次数 。
634 |
635 | ### Exercise 3 练习3
636 |
637 | A string slice can take a third index that specifies the “step size;” that is, the number of spaces between successive characters. A step size of 2 means every other character; 3 means every third, etc.
638 |
639 | > 字符串切片可以使用第三个索引,作为步长来使用;步长的意思就是取字符的间距。一个步长为2的意思就是每隔一个取一个字符;3的意思就是每次取第三个,以此类推。
640 |
641 | ```Python
642 | >>> fruit = 'banana'
643 | >>> fruit[0:5:2]
644 | 'bnn'
645 | ```
646 |
647 | A step size of -1 goes through the word backwards, so the slice \[::-1\]generates a reversed string.
648 | Use this idiom to write a one-line version of is\_palindrome from Exercise 3.
649 |
650 | > 步长如果为-1,意思就是倒序读取字符串,所以\[::-1\]这个切片就会生成一个逆序的字符串了。
651 | > 使用这个方法把练习三当中的is\_palindrome写成一个一行代码的版本。
652 |
653 | ### Exercise 4 练习4
654 |
655 | The following functions are all intended to check whether a string contains any lowercase letters, but at least some of them are wrong. For each function, describe what the function actually does \(assuming that the parameter is a string\).
656 |
657 | > 下面这些函数都试图检查一个字符串是不是包含小写字母,但他们当中肯定有些是错的。描述一下每个函数真正的行为(假设参数是一个字符串)。
658 |
659 | ```Python
660 | def any_lowercase1(s):
661 | for c in s:
662 | if c.islower():
663 | return True
664 | else:
665 | return False
666 |
667 | def any_lowercase2(s):
668 | for c in s:
669 | if 'c'.islower():
670 | return 'True'
671 | else:
672 | return 'False'
673 |
674 |
675 | def any_lowercase3(s):
676 | for c in s:
677 | flag = c.islower()
678 | return flag
679 |
680 | def any_lowercase4(s):
681 | flag = False
682 | for c in s:
683 | flag = flag or c.islower()
684 | return flag
685 |
686 | def any_lowercase5(s):
687 | for c in s:
688 | if not c.islower():
689 | return False
690 | return True
691 | ```
692 |
693 | ### Exercise 5 练习5
694 |
695 | A Caesar cypher is a weak form of encryption that involves “rotating” each letter by a fixed number of places. To rotate a letter means to shift it through the alphabet, wrapping around to the beginning if necessary, so ’A’ rotated by 3 is ’D’ and ’Z’ rotated by 1 is ’A’.
696 |
697 | > 凯撒密码是一种简单的加密方法,用的方法是把每个字母进行特定数量的移位。对一个字母移位就是把它根据字母表的顺序来增减对应,如果到末尾位数不够就从开头算剩余的位数,『A』移位3就是『D』,而『Z』移位1就是『A』了。
698 |
699 | To rotate a word, rotate each letter by the same amount. For example, “cheer” rotated by 7 is “jolly” and “melon” rotated by -10 is “cubed”. In the movie 2001: A Space Odyssey, the ship computer is called HAL, which is IBM rotated by -1.
700 |
701 | > 要对一个词进行移位,要把每个字母都移动同样的数量。比如『cheer』这个单词移位7就是『jolly』,而『melon』移位-10就是『cubed』。在电影《2001 太空漫游》中,飞船的电脑叫 HAL,就是 IBM 移位-1。
702 |
703 | Write a function called rotate\_word that takes a string and an integer as parameters, and returns a new string that contains the letters from the original string rotated by the given amount.
704 |
705 | > 写一个名叫 rotate\_word 的函数,接收一个字符串和一个整形为参数,返回将源字符串移位该整数位得到的新字符串。
706 |
707 | You might want to use the built-in function ord, which converts a character to a numeric code, and chr, which converts numeric codes to characters. Letters of the alphabet are encoded in alphabetical order, so for example:
708 |
709 | > 你也许会用得上内置函数 ord,它把字符转换成数值代码,然后还有个 chr 是用来把数值代码转换成字符。字母表中的字母都被编译成跟字母表中同样的顺序了,所以如下所示:
710 |
711 | ```Python
712 | >>> ord('c') - ord('a')
713 | 2
714 | ```
715 |
716 | Because 'c' is the two-eth letter of the alphabet. But beware: the numeric codes for upper case letters are different.
717 |
718 | > c 是字母表中的第『2』个(译者注:从0开始数哈)的位置,所以上述结果是2。但注意:大写字母的数值代码是和小写的不一样的。
719 |
720 | Potentially offensive jokes on the Internet are sometimes encoded in ROT13, which is a Caesar cypher with rotation 13. If you are not easily offended, find and decode some of them. [Solution](http://thinkpython2.com/code/rotate.py).
721 |
722 | > 网上很多有冒犯意义的玩笑都是用 ROT13加密的,也就是移位13的凯撒密码。如果你不太介意,找一下这些密码解密一下吧。[样例代码](http://thinkpython2.com/code/rotate.py).
723 |
724 |
725 |
726 |
--------------------------------------------------------------------------------
/ThinkPython-9.md:
--------------------------------------------------------------------------------
1 | Title: ThinkPython 双语学编程 Chapter 9
2 | Date: 2015-11-30
3 | Category: ThinkPython
4 | Tag: 双语,Python,ThinkPython
5 |
6 | #Chapter 9 Case study: word play 案例学习:单词游戏
7 |
8 | This chapter presents the second case study, which involves solving word puzzles by searching for words that have certain properties. For example, we’ll find the longest palindromes in English and search for words whose letters appear in alphabetical order. And I will present another program development plan: reduction to a previously-solved problem.
9 | >本章我们进行第二个案例学习,这一案例中涉及到了用搜索具有某些特征的单词来猜谜。比如,我们会发现英语中最长的回文词,然后搜索那些按照单词表顺序排列字母的单词。我还会给出一种新的程序开发计划:降低问题的复杂性和难度,还原到以前解决的问题。
10 |
11 | ##9.1 Reading word lists 读取字符列表
12 |
13 | For the exercises in this chapter we need a list of English words. There are lots of word lists available on the Web, but the one most suitable for our purpose is one of the word lists collected and contributed to the public domain by Grady Ward as part of the Moby lexicon project (see [Here](http://wikipedia.org/wiki/Moby_Project)). It is a list of 113,809 official crosswords; that is, words that are considered valid in crossword puzzles and other word games. In the Moby collection, the filename is 113809of.fic; you can download a copy, with the simpler name words.txt, from [Here](http://thinkpython2.com/code/words.txt).
14 | >本章练习中,咱们需要用一个英语词汇列表。网上有很多,不过最适合我们的列表并且是共有领域的,莫过于 Grady Ward这份词汇表,这是Moby词典计划的一部分(点击[此链接访问详情](http://wikipedia.org/wiki/Moby_Project))。这是一份113,809个公认的字谜表;也就是公认可以用于字谜游戏以及其他文字游戏的单词。在 Moby 的词汇项目中,该词表的文件名为113809of.fic;你可以下载一份副本,这里名字简化成 words.txt 了,下载地址[在这里](http://thinkpython2.com/code/words.txt)。
15 |
16 |
17 |
18 | This file is in plain text, so you can open it with a text editor, but you can also read it from Python. The built-in function open takes the name of the file as a parameter and returns a file object you can use to read the file.
19 | >这个文件就是纯文本,所以你可以用文本编辑器打开一下,不过也可以用 Python 来读取。Python 内置了一个叫open 的函数,接收文件名做参数,返回一个文件对象,你可以用它来读取文件。
20 |
21 |
22 | ```Python
23 | >>> fin = open('words.txt')
24 | ```
25 |
26 |
27 | fin is a common name for a file object used for input. The file object provides several methods for reading, including readline, which reads characters from the file until it gets to a newline and returns the result as a string:
28 | >fin 是一个用来表示输入的文件的常用名字。这个文件对象提供了好几种读取的方法,包括逐行读取,这种方法是读取文本中的一整行直到结尾,然后把读取的内容作为字符串返回:
29 |
30 |
31 | ```Python
32 | >>> fin.readline()
33 | 'aa\r\n'
34 | ```
35 |
36 |
37 |
38 | The first word in this particular list is “aa”, which is a kind of lava. The sequence \r\n represents two whitespace characters, a carriage return and a newline, that separate this word from the next.
39 | The file object keeps track of where it is in the file, so if you call readline again, you get the next word:
40 | >这一列当中的第一个词就是『aa』了,这是一种**熔岩**(译者注:“aa”是夏威夷词汇,音“阿阿”,用来描述表面粗糙的熔岩流。译者本人就是地学专业的,都很少接触这个词,本教材作者真博学啊)。后面跟着的\r\n 的意思代表着有两个转义字符,一个是回车,一个是换行,这样把这个单词从下一个单词分隔开来。
41 | >文件对象会记录这个单词在源文件中的位置,所以下次你再调用 readline 的时候,就能得到下一个词了:
42 |
43 |
44 |
45 | ```Python
46 | >>> fin.readline()
47 | 'aah\r\n'
48 | ```
49 |
50 |
51 | The next word is “aah”, which is a perfectly legitimate word, so stop looking at me like that. Or, if it’s the whitespace that’s bothering you, we can get rid of it with the string method strip:
52 | >下一个词是『aah』,这完全是一个正规的词汇,不要怪异眼神看我哦。另外如果转义字符让你很烦,咱们可以稍加修改来去掉它,用字符串的 strip 方法即可:
53 |
54 | ```Python
55 | >>> line = fin.readline()
56 | >>> word = line.strip()
57 | >>> word
58 | 'aahed'
59 | ```
60 |
61 |
62 | You can also use a file object as part of a for loop. This program reads words.txt and prints each word, one per line:
63 | >在 for 循环中也可以使用文件对象。下面的这个程序读取整个 words.txt 文件,然后每行输出一个词:
64 |
65 | ```Python
66 | fin = open('words.txt')
67 | for line in fin:
68 | word = line.strip()
69 | print(word)
70 | ```
71 |
72 |
73 | ##9.2 Exercises 练习
74 | There are solutions to these exercises in the next section. You should at least attempt each one before you read the solutions.
75 | >下面这些练习都有样例代码。不过你最好在看答案之前先自己对每个练习都尝试一下。
76 |
77 |
78 | ###Exercise 1 练习1
79 | Write a program that reads words.txt and prints only the words with more than 20 characters (not counting whitespace).
80 | >写一个程序读取 words.txt,然后只输出超过20个字母长度的词(这个长度不包括转义字符)。
81 |
82 | ###Exercise 2 练习2
83 |
84 | In 1939 Ernest Vincent Wright published a 50,000 word novel called Gadsby that does not contain the letter “e”. Since “e” is the most common letter in English, that’s not easy to do.
85 | >在1939年,作家厄尔尼斯特·文森特·莱特曾经写过一篇5万字的小说《葛士比》,里面没有一个字母e。因为在英语中 e 是用的次数最多的字母,所以这很不容易的。
86 |
87 | In fact, it is difficult to construct a solitary thought without using that most common symbol. It is slow going at first, but with caution and hours of training you can gradually gain facility.
88 | >事实上,不使用最常见的字符,都很难想出一个简单的想法。一开始很慢,不过仔细一些,经过几个小时的训练之后,你就逐渐能做到了。
89 |
90 | All right, I’ll stop now.
91 | Write a function called has_no_e that returns True if the given word doesn’t have the letter “e” in it.
92 | >好了,我不扯淡了。
93 | >写一个名字叫做 has_no_e 的函数,如果给定词汇不含有 e 就返回真,否则为假。
94 |
95 | Modify your program from the previous section to print only the words that have no “e” and compute the percentage of the words in the list that have no “e”.
96 | >修改一下上一节的程序代码,让它只打印单词表中没有 e 的词汇,并且统计一下这些词汇在总数中的百分比例。
97 |
98 |
99 | ###Exercise 3 练习3
100 | Write a function named avoids that takes a word and a string of forbidden letters, and that returns True if the word doesn’t use any of the forbidden letters.
101 | Modify your program to prompt the user to enter a string of forbidden letters and then print the number of words that don’t contain any of them. Can you find a combination of 5 forbidden letters that excludes the smallest number of words?
102 | >写一个名叫 avoids 的函数,接收一个单词和一个禁用字母组合的字符串,如果单词不含有该字符串中的任何字母,就返回真。
103 | >修改一下程序代码,提示用户输入一个禁用字母组合的字符串,然后输入不含有这些字母的单词数目。你能找到5个被禁用字母组合,排除单词数最少吗?
104 |
105 |
106 |
107 | ###Exercise 4 练习4
108 | Write a function named uses_only that takes a word and a string of letters, and that returns True if the word contains only letters in the list. Can you make a sentence using only the letters acefhlo? Other than “Hoe alfalfa”?
109 | >写一个名叫uses_only的函数,接收一个单词和一个字母字符串,如果单词仅包含该字符串中的字母,就返回真。你能仅仅用 acefhlo 这几个字母造句子么?或者试试『Hoe alfalfa』?
110 |
111 | ###Exercise 5 练习5
112 | Write a function named uses_all that takes a word and a string of required letters, and that returns True if the word uses all the required letters at least once. How many words are there that use all the vowels aeiou? How about aeiouy?
113 | >写一个名字叫uses_all的函数,接收一个单词和一个必需字母组合的字符串,如果单词对必需字母组合中的字母至少都用了一次就返回真。有多少单词都用到了所有的元音字母 aeiou?aeiouy的呢?
114 |
115 |
116 |
117 | ###Exercise 6 练习6
118 | Write a function called is_abecedarian that returns True if the letters in a word appear in alphabetical order (double letters are ok). How many abecedarian words are there?
119 | >写一个名字叫is_abecedarian的函数,如果单词中所有字母都是按照字母表顺序出现就返回真(重叠字母也是允许的)。有多少这样的单词?
120 |
121 |
122 |
123 |
124 | ##9.3 Search 搜索
125 | All of the exercises in the previous section have something in common; they can be solved with the search pattern we saw in Section 8.6. The simplest example is:
126 | >刚刚的那些练习都有一些相似之处:都可以用我们在8.6学过的搜索来解决。下面是一个最简化的例子:
127 |
128 | ```Python
129 | def has_no_e(word):
130 | for letter in word:
131 | if letter == 'e':
132 | return False
133 | return True
134 | ```
135 |
136 |
137 |
138 | The for loop traverses the characters in word. If we find the letter “e”, we can immediately return False; otherwise we have to go to the next letter. If we exit the loop normally, that means we didn’t find an “e”, so we return True.
139 | >这个 for 循环遍历了单词的所有字母。如果找到了字母e,就立即返回假;否则就到下一个字母。如果正常退出了循环,意味着我们没找到 e,就返回真。
140 |
141 |
142 | You could write this function more concisely using the in operator, but I started with this version because it demonstrates the logic of the search pattern.
143 | avoids is a more general version of has_no_e but it has the same structure:
144 | >你可以使用 in 运算符,把这个函数写得更精简,我之所以用一个稍显麻烦的版本,是为了说明搜索模式的逻辑过程。
145 | >avoids 是一个更通用版本的has_no_e函数的实现,它的结构是一样的:
146 |
147 | ```Python
148 | def avoids(word, forbidden):
149 | for letter in word:
150 | if letter in forbidden:
151 | return False
152 | return True
153 | ```
154 |
155 | We can return False as soon as we find a forbidden letter; if we get to the end of the loop, we return True.
156 | uses_only is similar except that the sense of the condition is reversed:
157 | >只要找到了禁用字母就可以立即返回假;如果运行到了循环末尾,就返回真。
158 | >uses_only与之相似,无非是条件与之相反了而已。
159 |
160 | ```Python
161 | def uses_only(word, available):
162 | for letter in word:
163 | if letter not in available:
164 | return False
165 | return True
166 | ```
167 |
168 |
169 | Instead of a list of forbidden letters, we have a list of available letters. If we find a letter in word that is not in available, we can return False.
170 | uses_all is similar except that we reverse the role of the word and the string of letters:
171 | >这次不是有一个禁用字母列表,我们这次用一个可用字母列表。如果在单词中发现不在可用字母列表中的,就返回假了。
172 | >uses_all这个函数与之也相似,不过我们转换了单词和字母字符串的角色:
173 |
174 | ```Python
175 | def uses_all(word, required):
176 | for letter in required:
177 | if letter not in word:
178 | return False
179 | return True
180 | ```
181 |
182 |
183 |
184 | Instead of traversing the letters in word, the loop traverses the required letters. If any of the required letters do not appear in the word, we can return False.
185 | If you were really thinking like a computer scientist, you would have recognized that uses_all was an instance of a previously-solved problem, and you would have written:
186 | >这次并没有遍历单词中的所有字母,循环遍历了所有指定的字母。如果有任何指定字母没有在单词中出新啊,就返回假。如果你已经像计算机科学家一样思考了,你就应该已经发现了uses_all是对之前我们解决过问题的一个实例,你已经写过这个代码了:
187 |
188 | ```Python
189 | def uses_all(word, required):
190 | return uses_only(required, word)
191 | ```
192 |
193 |
194 | This is an example of a program development plan called reduction to a previously-solved problem, which means that you recognize the problem you are working on as an instance of a solved problem and apply an existing solution.
195 | >这就是一种新的程序开发规划模式,就是降低问题的复杂性和难度,还原到以前解决的问题,意思是你发现正在面对的问题是之前解决过的问题的一个实例,就可以用已经存在的方案来解决。
196 |
197 |
198 |
199 |
200 | ##9.4 Looping with indices 带索引循环
201 |
202 | I wrote the functions in the previous section with for loops because I only needed the characters in the strings; I didn’t have to do anything with the indices.
203 | For is_abecedarian we have to compare adjacent letters, which is a little tricky with a for loop:
204 | >上面的章节中我写了各种用 for 循环的函数,因为当时只需要字符串中的字符;这就不需要理会索引。
205 | >但is_abecedarian这个函数中,我们需要对比临近的两个字母,所以用 for 循环就不那么好写了:
206 |
207 | ```Python
208 | def is_abecedarian(word):
209 | previous = word[0]
210 | for c in word:
211 | if c < previous:
212 | return False
213 | previous = c
214 | return True
215 | ```
216 |
217 |
218 | An alternative is to use recursion:
219 | >一种很好的替代思路就是使用递归:
220 |
221 |
222 | ```Python
223 | def is_abecedarian(word):
224 | if len(word) <= 1:
225 | return True
226 | if word[0] > word[1]:
227 | return False
228 | return is_abecedarian(word[1:])
229 | ```
230 |
231 |
232 | Another option is to use a while loop:
233 | >另外一种方法是用 while 循环:
234 |
235 | ```Python
236 | def is_abecedarian(word):
237 | i = 0
238 | while i < len(word)-1:
239 | if word[i+1] < word[i]:
240 | return False
241 | i = i+1
242 | return True
243 | ```
244 |
245 | The loop starts at i=0 and ends when i=len(word)-1. Each time through the loop, it compares the ith character (which you can think of as the current character) to the i+1th character (which you can think of as the next).
246 | >循环开始于 i 等于0,然后在 i 等于len(word)-1的时候结束。每次通过循环的时候,都对比第 i 个字符(你可以就当是当前字符)与第 i+1个字符(就当作下一个字符)。
247 |
248 | If the next character is less than (alphabetically before) the current one, then we have discovered a break in the abecedarian trend, and we return False.
249 | >如果下一个字符比当前字符小(字母表排列顺序在当前字符前面),我们就发现这个不符合字母表顺序了,跳出返回假就可以了。
250 |
251 | If we get to the end of the loop without finding a fault, then the word passes the test. To convince yourself that the loop ends correctly, consider an example like 'flossy'. The length of the word is 6, so the last time the loop runs is when i is 4, which is the index of the second-to-last character. On the last iteration, it compares the second-to-last character to the last, which is what we want.
252 | >如果一直到循环结尾都没有发现问题,这个词就通过检验了。为了确信循环正确结束了,可以拿单词『flossy』作为例子来试试。单词长度是6,所以循环终止的时候 i 应该是4,也就是倒数第二个位置。在最后一次循环中,比较的是倒数第二个和最后一个字母,这正是符合我们设计的。
253 |
254 | Here is a version of is_palindrome (see Exercise 3) that uses two indices; one starts at the beginning and goes up; the other starts at the end and goes down.
255 | >下面这个是练习3的is_palindrome的一个版本,使用了两个索引;一个从头开始一直到结尾;另外一个从末尾开始逆序进行。
256 |
257 | ```Python
258 | def is_palindrome(word):
259 | i = 0
260 | j = len(word)-1
261 | while i或者我们可以把问题解构成之前解决过的样式,然后这样写:
273 |
274 | ```Python
275 | def is_palindrome(word):
276 | return is_reverse(word, word)
277 | ```
278 |
279 | Using is_reverse from Section 8.11.
280 | >这里的is_reverse这个函数在第8章第11节讲过哈。
281 |
282 |
283 |
284 | ##9.5 Debugging 调试
285 |
286 | Testing programs is hard. The functions in this chapter are relatively easy to test because you can check the results by hand. Even so, it is somewhere between difficult and impossible to choose a set of words that test for all possible errors.
287 | >测试程序很难的。本章的函数相对来说还算容易测试,因为你可以手动计算来检验结果。即便如此,选择一系列单词然后检测所有可能的错误,可能不仅是做起来困难,甚至都是不可能完成的任务。
288 |
289 |
290 | Taking has_no_e as an example, there are two obvious cases to check: words that have an ‘e’ should return False, and words that don’t should return True. You should have no trouble coming up with one of each.
291 | >比如以has_no_e为例,有两种情况用来检查:有 e 的单词应该返回假,不包含 e 的单词要返回真。你自己想出几个这样的单词来检验一下并不难。
292 |
293 |
294 | Within each case, there are some less obvious subcases. Among the words that have an “e”, you should test words with an “e” at the beginning, the end, and somewhere in the middle. You should test long words, short words, and very short words, like the empty string. The empty string is an example of a special case, which is one of the non-obvious cases where errors often lurk.
295 | >在每个分支内,有一些不那么清晰的次级分支。在那些有 e 的单词中,你还要检测单词中的 e 是在开头结尾还是中间位置。你得试试长词、短词,甚至特别短的词,比如空字符串。空字符串是一个典型特例,这个情况很容易被忽视而成为潜伏的隐患。
296 | >(译者注:我知道,这段翻译的简直就是 shit,但是没办法,我这会眼睛特别疼,思路不太清楚,另外这几个练习也不是很难,大家很容易自己搞定。)
297 |
298 |
299 | In addition to the test cases you generate, you can also test your program with a word list like words.txt. By scanning the output, you might be able to catch errors, but be careful: you might catch one kind of error (words that should not be included, but are) and not another (words that should be included, but aren’t).
300 | >除了你自己设计的测试案例之外,你也可以用一个单词列表比如 words.txt 之类的来测试一下你的程序。通过扫描一下输出内容,你也许能够发现错误的地方,但一定要小心:你有可能发现某一种特定错误,但忽略了另外一个,比如包含了不应该包含的单词,但很难发现应该包含但遗漏了单词的情况。
301 |
302 | In general, testing can help you find bugs, but it is not easy to generate a good set of test cases, and even if you do, you can’t be sure your program is correct. According to a legendary computer scientist:
303 | Program testing can be used to show the presence of bugs, but never to show their absence!
304 | — Edsger W. Dijkstra
305 | >总的来说,测试程序能帮助你找到错误地方,但很难找到一系列特别好的测试案例,或者即便你找了很多案例来测试,也不能确保程序就是正确的。一位传说级别的计算机科学家说:
306 | >程序测试可以用来表明 bug 的存在,但永远不能表明 bug 不存在。
307 | >— Edsger W. Dijkstra
308 |
309 |
310 | ##9.6 Glossary 术语列表
311 |
312 | file object:
313 | A value that represents an open file.
314 | >文件对象:代表了一份打开的文件的值。
315 |
316 | reduction to a previously-solved problem:
317 | A way of solving a problem by expressing it as an instance of a previously-solved problem.
318 | >降低问题的复杂性和难度,还原到以前解决的问题:一种解决问题的方法,把问题表达成过去解决过问题的一个特例。
319 |
320 | special case:
321 | A test case that is a typical or non-obvious (and less likely to be handled correctly).
322 | >特殊案例:很典型或者不明显的测试用的案例,往往都很不容易正确处理。
323 |
324 |
325 |
326 | ##9.7 Exercises 练习
327 |
328 | ###Exercise 7 练习7
329 | [This question](http://www.cartalk.com/content/puzzlers)is based on a Puzzler that was broadcast on the radio program Car Talk :
330 | Give me a word with three consecutive double letters. I’ll give you a couple of words that almost qualify, but don’t. For example, the word committee, c-o-m-m-i-t-t-e-e. It would be great except for the ‘i’ that sneaks in there. Or Mississippi: M-i-s-s-i-s-s-i-p-p-i. If you could take out those i’s it would work. But there is a word that has three consecutive pairs of letters and to the best of my knowledge this may be the only word. Of course there are probably 500 more but I can only think of one. What is the word?
331 | Write a program to find it.
332 | [Solution](http://thinkpython2.com/code/cartalk1.py)
333 | >[这个问题](http://www.cartalk.com/content/puzzlers)基于一个谜语,这个谜语在广播节目 Car Talk 上面播放过:
334 | >给我一个有三个连续双字母的单词。我会给你一对基本符合的单词,但并不符合。例如, committee 这个单词,C O M M I T E。如果不是有单独的一个 i 在里面,就基本完美了,或者Mississippi 这个词:M I S I S I P I。如果把这些个 i 都去掉就好了。但有一个词正好是三个重叠字母,而且据我所知这个词可能是唯一一个这样的词。当然有有可能这种单词有五百多个呢,但我只能想到一个。是哪个词呢?写个程序来找一下这个词吧。
335 | >[样例代码](http://thinkpython2.com/code/cartalk1.py)
336 |
337 |
338 |
339 | ###Exercise 8 练习8
340 | [Here](http://www.cartalk.com/content/puzzlers)’s another Car Talk Puzzler :
341 | “I was driving on the highway the other day and I happened to notice my odometer. Like most odometers, it shows six digits, in whole miles only. So, if my car had 300,000 miles, for example, I’d see 3-0-0-0-0-0.
342 | “Now, what I saw that day was very interesting. I noticed that the last 4 digits were palindromic; that is, they read the same forward as backward. For example, 5-4-4-5 is a palindrome, so my odometer could have read 3-1-5-4-4-5.
343 | “One mile later, the last 5 numbers were palindromic. For example, it could have read 3-6-5-4-5-6. One mile after that, the middle 4 out of 6 numbers were palindromic. And you ready for this? One mile later, all 6 were palindromic!
344 | “The question is, what was on the odometer when I first looked?”
345 | Write a Python program that tests all the six-digit numbers and prints any numbers that satisfy these requirements. [Solution](http://thinkpython2.com/code/cartalk2.py)
346 | >[这个](http://www.cartalk.com/content/puzzlers)又是一个 Car Talk 谜语:
347 | >有一天我在高速路上开着车,碰巧看了眼里程表。和大多数里程表一样,是六位数字的,单位是英里。加入我的车跑过300,000英里了,看到的结果就是3-0-0-0-0-0.
348 | >我那天看到的很有趣,我看到后四位是回文的;就是说后四位正序和逆序读是一样的。例如5-4-4-5就是一个回文数,所以我的里程表可能读书就是3-1-5-4-4-5.
349 | >过了一英里之后,后五位数字是回文的了。举个例子,可能读书就是3-6-5-4-5-6。又过了一英里,六个数字中间的数字是回文数了。准备好更复杂的了么?又过了一英里,整个六位数都是回文的了!
350 | >那么问题俩了:我最开始看到的里程表的度数应该是多少?
351 | >写个 Python 程序来检测一下所有的六位数,然后输出一下满足这些要求的数字。 [样例代码](http://thinkpython2.com/code/cartalk2.py)
352 |
353 |
354 |
355 | ###Exercise 9 练习9
356 | [Here](http://www.cartalk.com/content/puzzlers)’s another Car Talk Puzzler you can solve with a search :
357 | “Recently I had a visit with my mom and we realized that the two digits that make up my age when reversed resulted in her age. For example, if she’s 73, I’m 37. We wondered how often this has happened over the years but we got sidetracked with other topics and we never came up with an answer.
358 | “When I got home I figured out that the digits of our ages have been reversible six times so far. I also figured out that if we’re lucky it would happen again in a few years, and if we’re really lucky it would happen one more time after that. In other words, it would have happened 8 times over all. So the question is, how old am I now?”
359 | Write a Python program that searches for solutions to this Puzzler. Hint: you might find the string method zfill useful.
360 | [Solution](http://thinkpython2.com/code/cartalk3.py)
361 | >[这个](http://www.cartalk.com/content/puzzlers)又是一个 Car Talk 谜语,你可以用搜索来解决:
362 | >最近我看忘了妈妈,然后我们发现我的年龄反过来正好是她的年龄。例如,假如他是73岁,我就是37岁了。我们好奇这种情况发生多少次,但中间叉开了话题,没有想出来这个问题的答案。
363 | >我回家之后,我发现到目前位置我们的年龄互为逆序已经是六次了,我还发现如果我们幸运的话过几年又会有一次,如果我们特别幸运,就还会再有一次这样情况。换句话说,就是总共能有八次。那么问题来了:我现在多大了?
364 | >写一个 Python 程序,搜索一下这个谜语的解。提示一下:你可能发现字符串的 zfill 方法很有用哦。
365 | >[样例代码](http://thinkpython2.com/code/cartalk3.py)
366 |
367 |
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/cover.jpg
--------------------------------------------------------------------------------
/images/figure10.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure10.1.jpg
--------------------------------------------------------------------------------
/images/figure10.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure10.2.jpg
--------------------------------------------------------------------------------
/images/figure10.3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure10.3.jpg
--------------------------------------------------------------------------------
/images/figure10.4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure10.4.jpg
--------------------------------------------------------------------------------
/images/figure10.5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure10.5.jpg
--------------------------------------------------------------------------------
/images/figure11.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure11.1.jpg
--------------------------------------------------------------------------------
/images/figure11.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure11.2.jpg
--------------------------------------------------------------------------------
/images/figure12.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure12.1.jpg
--------------------------------------------------------------------------------
/images/figure12.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure12.2.jpg
--------------------------------------------------------------------------------
/images/figure15.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure15.1.jpg
--------------------------------------------------------------------------------
/images/figure15.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure15.2.jpg
--------------------------------------------------------------------------------
/images/figure15.3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure15.3.jpg
--------------------------------------------------------------------------------
/images/figure16.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure16.1.jpg
--------------------------------------------------------------------------------
/images/figure18.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure18.1.jpg
--------------------------------------------------------------------------------
/images/figure18.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure18.2.jpg
--------------------------------------------------------------------------------
/images/figure2.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure2.1.jpg
--------------------------------------------------------------------------------
/images/figure3.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure3.1.jpg
--------------------------------------------------------------------------------
/images/figure4.1-4.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure4.1-4.2.jpg
--------------------------------------------------------------------------------
/images/figure5.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure5.1.jpg
--------------------------------------------------------------------------------
/images/figure5.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure5.2.jpg
--------------------------------------------------------------------------------
/images/figure6.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure6.1.jpg
--------------------------------------------------------------------------------
/images/figure7.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure7.1.jpg
--------------------------------------------------------------------------------
/images/figure8.1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure8.1.jpg
--------------------------------------------------------------------------------
/images/figure8.2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/images/figure8.2.jpg
--------------------------------------------------------------------------------
/intro.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cycleuser/ThinkPython2-en-cn/6cccda4983780b760ff4e1c599015951f2f5cba1/intro.md
--------------------------------------------------------------------------------