diff --git a/.github/workflows/honkit-depoly.yml b/.github/workflows/honkit-depoly.yml new file mode 100644 index 00000000..c8a23c84 --- /dev/null +++ b/.github/workflows/honkit-depoly.yml @@ -0,0 +1,47 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Build Pages + uses: FriesI23/honkit-build-page@v2 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: "_site" + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/02.dedication.md b/02.dedication.md new file mode 100644 index 00000000..7cbbf7d5 --- /dev/null +++ b/02.dedication.md @@ -0,0 +1,7 @@ +# 献词 + +本书献给 [Kalyan Varma](http://www.kalyanvarma.net/) 以及其他许多来自 [PESIT](http://www.pes.edu/) 的先驱,是他们向我们介绍了来自 GNU/Linux 世界的开放源代码。 + +谨以此书纪念 [Atul Chitnis](http://www.nextbigwhat.com/atul-chitnis-obituary-297/),一位友人以及非常怀念他的人的引导者。 + +本书献给 [创造互联网的开拓者们](http://www.ibiblio.org/pioneers/index.html)。本书初撰于 2003 年。得益于这些先驱们对互联网上这一分享知识的土壤与环境的设想,本书得以流行至今,并对他们深表感谢。 \ No newline at end of file diff --git a/03.1.preface.md b/03.1.preface.md new file mode 100644 index 00000000..ef58c74c --- /dev/null +++ b/03.1.preface.md @@ -0,0 +1,27 @@ +# 前言 + +Python 可能是极少数能够同时兼顾简单与功能强大的编程语言。无论是对于新手或是行家,这一点都裨益颇深。更重要的是,采用 Python 编程充满了乐趣。本书旨在于帮助你学习这一美妙的程序语言,并向你展现如何快速且毫不费力地完成诸多事情,实际上也可说是“助你解决编程问题的抗毒血清”。 + +## 本书是为谁而撰 + +本书将以指南或教程的形式向你介绍 Python 这门编程语言。它以新手为主要目标。同时本书也对有经验的程序员有所帮助。 + +如果你对电脑的所有了解仅止步于如何保存文本文件的话,那本书的目标便是协助你通过本书学习 Python。如果在此之前你已经有了编程经验,你同样可以通过本书来学习 Python。 + +如果你已经有过编程经验,你或许会对 Python 与其它你所喜爱的编程语言间有何区别抱有兴趣——而我将会你展现许多这种区别。顺便提醒你一下,Python 将会很快成为你最喜欢的编程语言! + +## 官方网站 + +本书英文原版的官方网站是 {{ book.officialUrl }} ,在此你可以在线阅读本书的全部内容,下载本书的最新版本,[购买本书的实体版]({{ book.buyBookUrl }}),或是向我提交反馈。 + +你现在阅读的这一简体中文版的刊载网站是 {{ book.sctransUrl }} ,你可以在此在线阅读本书的简体中文版,并下载最新版本。 + +## 值得思考的一些事情 + +> 构建一项软件设计有两种方式:一种是将软件设计得足够简单以至于明显找不到缺陷;另一种是软件设计得足够复杂以至于找不到明显的缺陷。 +> ——查尔斯·安东尼·理查德·霍尔爵士(C. A. R. Hoare) + + + +> 在人生中取得成功,与其说靠天才与机会,不如说靠专注与毅力。 +> ——C. W. Wendte diff --git a/03.2.translator-preface.md b/03.2.translator-preface.md new file mode 100644 index 00000000..97d554d9 --- /dev/null +++ b/03.2.translator-preface.md @@ -0,0 +1,51 @@ +# 译者前言 + +如果一位新手想要学习编程,那么 Python 一定能排在推荐清单的最前列。而如果要想学习 Python,Swaroop C H 所撰写的《A Byte of Python》一定也能排在推荐教材的靠前位置。作为一本旨在简明、易懂地传授 Python 知识的教材,这本采用知识共享协议免费分发的图书一经刊行就流行于世界各地,不仅被翻译成各种语言,还被许多大学或教育机构采用用作正式的教学教材。它在中国还有一个流传已久的名字——《简明 Python 教程》。 + +2005 年,沈洁元将《Byte of Python》的 1.20 版本引进中国,并完成了全本翻译,将其译名定为《简明 Python 教程》。十余年来,这一译本流行于各大网站,想必自是为无数新晋的 Python 学习者以及业已有编程经验的程序员们提供了莫大帮助。 + +如今这份教程的中文译本的年龄已逾 11 年,原书《Byte of Python》已有诸多改动,而 Python 亦已历经多个重大更新。最简单的情况便是,在 Python 2 更新至 Python 3 后,译本中开头的第一个程序 `print 'hello world'` 这一写法已经不再适用于 Python 3。可以料想,这个问题已对不少学习者成了他们在学习 Python 时面对的第一个困扰。 + +这也是促使我这个兴趣使然的编程新手开始试图重新翻译这本教程的原因。计算机技术、程序与应用开发技术的发展可能比其他任何一项技术更能贴合日新月异这样的说法,而有关 Python 由 2 至 3 的改动是否得当、应当使用哪一个版本这些议题到今天依然争执不休。即便如此,一本简明教程或许仍有其紧跟时代的必要,在所有资料都准备就绪后,才可对后来的新入门者提供更全面的帮助,产生更为有利的影响。 + +于是,自一个兴起而至的想法启程,今天我心怀忐忑地带来这本从头重新翻译的《简明 Python 教程》的新译本。 + +本译本根据《Byte of Python》原书在 [GitHub](https://github.com/swaroopch/byte-of-python) 上提供的原文件进行翻译。根据原书中提供的修订历史信息,译本遵循同样的版本号,定义为 4.0c 版。本次翻译除了正文内容外,还翻译了其他介绍章节、附录章节以及其中的读者来稿与感言。书中所附的 .py 文件及直接写入正文中的的源代码酌情翻译了注释部分。但为了保证程序源代码中的整洁与避免不必要的修改,程序案例源码中的英文语句没有翻译而保持原样。 + +由于沈洁元所发布的 1.20 版译本是基于 [CC BY-NC-ND 1.0](https://creativecommons.org/licenses/by-nd-nc/1.0/)(署名-非商业使用-禁止演绎,在译本发布时写作“署名-非派生作品-非商业用途”)协议进行授权与分发,因此这一重译本不能在沈的译本上进行改动或采纳其已有的更有力的表述,而只能将其列为参考。但在此依旧要向沈洁元的翻译工作表示感谢,这份开辟性的译本对本译本的翻译提供了诸多参考,在这十数年间为无数学习者起到了至关重要的帮助。新译本不敢抱持多少野心,只希望能够继承先前译本所能起到的作用——哪怕只有些许。 + +另外,作为同一本书不同修订版的前后译本,为使阅读过沈洁元译本的读者便于通过本书了解新增的内容,同时也为避免对同一概念的不同表达可能造成的困扰,对于本译本与沈洁元译本译法相左的一些术语或概念,会在注释中列出了沈洁元译本采用的译法,供读者参考。 + +有关现在这本新译本,翻译并非一蹴而就,期间磕磕绊绊也是必然。事实上现在这位新译者在刚开始翻译时仍是一名编程门外汉,仅抱着兴趣使然的心与一边翻译一边学习的浅薄想法而仓促启程。只不过在抵达终点时仍担心不已,不知是否已实现出发时的雄心壮志。因此,读者诸君在阅读本译本时如果遇到了任何表达上的疑惑,或是发现了任何翻译上的错误,还请务必与译者联系,指出个中疑惑或疏漏、错误,以便更好地改进这一译本,为后来的其他学习者提供更为有用的帮助。 + +在翻译过程中,译者得到了诸如 Nakagawa Kanon,Zxteloiv,Yukko 等其他不能一一列清姓名的友人帮助,是他们向我解释概念,提出更精准的译法。在面对我这一个新手时常流露出的无知与莽撞时他们所展现出的包容和耐心予我莫大鼓励,在此要对他们表示感谢。 + +有关对于本书内容方面的感想或谢意,你可以将其直接寄给原作者 [SwaroopC H](blog@swaroopch.com)(blog@swaroopch.com)。有关译本在翻译方面存在的任何疑惑与问题,你可以通过[电子邮件](mailto:i@molun.net)(i@molun.net)与译者取得联系。而受限于译者在编程方面的浅薄学识,对于本书在学习过程中产生的编程方面的疑惑,很可能不能为读者诸君提供有用的解答,这点还望见谅。 + +在此,预祝你的 Python 学习之路能一路畅通无阻,携坚持与毅力出发,最后满载而归。 + +漠伦 + +2017年1月2日 + +## 修订追记 + +本书在译成后得到了诸多读者的指正,以下列出对本译本的修改提出过建议的读者,并感谢他们的意见与建议。所有排名不分先后。 + +2017 年 1 月 3 日至 1 月 8 日,陆续进行了错字漏字的订正。依 anglum 与 slimray 的建议对《面向对象编程》一章的部分翻译作了修改,并修正了错误。经 行走的鱼2001 指正改正了《函数》一章的错误。经 lefinite 指正改正了《数据结构》一章的错误。经 Zhanyu Wang 指正改正了《模块》一章的错误。经 nonozone 与 张小西 指正改正了《基础》一章的错误。在 ivysrono 协助下改正了《函数》《模块》两章的错误。——以上修订体现在 4.01c 版中。 + +2017年 1 月 9 日至 2 月 16 日,陆续进行了错字漏字订正与部分译文重写。依 Haruki Kirigaya、Yuki Kiriyama、Nakagawa Kanon 指正改写了《面向对象编程》一章的部分译文。经 Cloud 指正改正了《运算符与表达式》一章的错误。经 yurikaka 指正改正了《前言》《基础》《运算符与表达式》几章的错误。经 aristotll 指正改正了《标准库》一章的错误。经 Tian Zhao 指正改正了《解决问题》一章的错误。——以上修订体现在 4.02c 版中。 + +2017 年 3 月 19 日,进行了错字漏字订正。依 Tian Zhao 指正,改正了《解决问题》一章的错误。依 yangyangwithgnu 指正修改了《基础》《函数》《模块》《解决问题》《面向对象编程》《数据结构》《标准库》《迈出下一步》《FLOSS》章节的错误。追忆、Yang 同样指出了前述的部分错误。——以上修订体现在 4.03c 版中。 + +2017 年 5 月 1 日,进行了错字漏字订正与部分译文重写。依 Nangcr 建议修改了《控制流》一章的部分措辞。依邹鹏、Haruki Kirigaya、Yuki Kiriyama、藍星アキラ、shuven 指正与建议改写了《面向对象编程》一章的部分译文与多处翻译错误。——以上修订体现在 4.04c 版中。 + +2017 年 7 月 6 日,进行了错字漏字订正。在 shuizhongyueming 的帮助下修改了《运算符与表达式》《安装》《面向对象编程》章节的错误。在 Leon0824 的帮助下修改了《基础》《函数》《模块》几章的错误。依 cobeee 指正修改了《翻译》一章的错误。依 Alexander Nie 的指正调整了《函数》章节的部分内容。依 192\*\*\*\*543 指正修改了《第一步》章节的错误。依 薛景老师 指正改正了《关于 Python》章节的错误。依 genkagen 指正改正了《异常》《输入与输出》章节的错误。依 nastydt 指正改正了《面向对象编程》《运算符与表达式》一章的错误。依 wang454 指正改正了某一示例程序的错误。——以上修订体现在 4.05c 版中。 + +2017 年 7 月 28 日,进行了错字漏字订正。依 David Wang 的指正改正了《更多》《迈出下一步》章节的错误。依 薛景老师 指正改成了《第一步》《基础》《运算符与表达式》《控制流》章节的错误。依 Lulu Zeng 指正修改了《面向对象编程》章节的错误。依 LazyWolf Lin 指正与建议修改了《控制流》《函数》章节的错误与措辞。依 Kuno Kuno 指正修改了《面向对象编程》章节的错误。依 Cobeee 指正修改了《本书由来》章节的错误。本次修订得到了 Haruki Kirigaya 的协助,他参与修改了部分上述提到的错误,并指出了其它错误,具体章节包括《第一步》《基础》《运算符与表达式》《控制流》《函数》《解决问题》《面向对象编程》《异常》,在此深表感谢。——以上修订体现在 4.06c 版中。 + +2017 年 11 月 1 日,对错字漏字以及误译错译进行了集中修订。依 Lyfeway 指正修改了《数据结构》《面向对象编程》一章的错误。依单行道指正修改了《附录:本书由来》一章的错误。依 Starnight Cyber 指正修改了《基础》一章的错误。依chchuj 指正修改了《面向对象编程》一章的错误。依 YangtseSu 指正修改了《模块》一章的错误。依小陈指正改正了《数据结构》一章的错误。依夜雨指正改正了《函数》一章的错误。在本次修订过程中,来自 Little Train Branch 群组的朋友 Haruka、Haruki Kirigaya、Yuki Kiriyama、藍星アキラ 检查了修订草稿,并对多处修订方案提出了具体的建议,同时还指出了先前尚未发现的错误,在此向他们表示感谢。——以上修订体现在 4.07c 版中。 + +2018 年 2 月 4 日,对错字漏字与错译误译进行了集中修订。依颜、urzeye 指正改正了《基础》一章的错误。依 Cobeee 指正修改了《基础》《控制流》《译者前言》章节的错误,对误记了他的名字深表歉意。依 Shihaotian 的建议调整了《函数》一章中一个示例程序的输出内容。依 Xiaolei Wang 指正改正了《基础》一章的错误。依 ddtyjmyjm 指正改正了《异常》一章的错误。依 whxaing 指正改正了《函数》一章的错误。依 David Jiang 指正改正了《安装》《基础》《运算符与表达式》《模块》《数据结构》《输入与输出》《迈出下一步》《附录:修订历史》章节的错误。依 gooyie 指正改正了《运算符与标表达式》章节的错误,Haruka、Haruki Kirigaya、Yuki Kiriyama、藍星アキラ 参与了有关本修正的讨论,并提供了相关建议。——以上修订体现在 4.08c 版中。 + +同时,由于域名配置问题,从 4.08c 版开始,本书存放域名由 bop.molun.net 迁移至 bop.mol.uno。原域名理论上依旧有效。 \ No newline at end of file diff --git a/04.about_python.md b/04.about_python.md new file mode 100644 index 00000000..1399f29f --- /dev/null +++ b/04.about_python.md @@ -0,0 +1,90 @@ +# 关于 Python + +Python 是一种极少数能声言兼具 _简单_ 与 _功能强大_ 的编程语言。你将惊异于发现你正在使用的这门编程语言是如此简单,它专注于如何解决问题,而非拘泥于语法与结构。 + +官方对 Python 的介绍如下: + +> Python 是一款易于学习且功能强大的编程语言。 它具有高效率的数据结构,能够简单又有效地实现面向对象编程。Python 简洁的语法与动态输入之特性,加之其解释性语言的本质,使得它成为一种在多种领域与绝大多数平台都能进行脚本编写与应用快速开发工作的理想语言。 + +我将会在下一节详细讨论这些特性。 + +## 名字背后的故事 + +Python 的创造者吉多·范罗苏姆(Guido van Rossum)采用 BBC 电视节目《蒙提·派森的飞行马戏团(Monty Python's Flying Circus,一译巨蟒剧团)》的名字来为这门编程语言命名。尽管他本人并不特别喜欢蟒蛇这种通过在猎物身边卷曲自己的身体以此来碾碎猎物身体来进食的动物。 + +## Python 的特色 + +### 简单 + +Python 是一门简单且简约的语言。阅读一份优秀的 Python 程序代码就如同在阅读英语文章一样,尽管这门英语要求十分严格!Python 这种伪代码式的特质正是它的一大优势。它能够让你专注于解决问题的方案,而不是语言本身。 + +### 易于学习 + +正如你接下来将看到的,Python 是一门非常容易入门的语言。正如前面所提到的,Python 有一套极其简单的语法体系。 + +### 自由且开放 + +Python 是 FLOSS (自由/开放源代码软件)的成员之一。简单来说,你可以自由地分发这一软件的拷贝,阅读它的源代码,并对其作出改动,或是将其的一部分运用于一款新的自由程序中。FLOSS 基于一个可以分享知识的社区理念而创建。这正是 Python 为何能如此优秀的一大原因——它由一群希望看到 Python 能变得更好的社区成员所创造,并持续改进至今。 + +### 高级语言 + +当你在用 Python 编写程序时,你不必考虑诸如你的程序应当如何使用内存等底层细节。 + +### 跨平台性 + +由于其开放源码的特性,Python 已被移植到其它诸多平台(意即它们已经过改动以保证其能正常工作)。如果你小心地避开了所有系统依赖型的特性。你所有的 Python 程序可以在其中任何一个平台上工作,不必作出任何改动。 + +你可以在 GNU/Linux、Windows、FreeBSD、Macintosh、 Solaris、 OS/2、 Amiga、 AROS、 AS/400、 BeOS、 OS/390、 z/OS、 Palm OS、 QNX、 VMS、 Psion、 Acorn RISC OS、 VxWorks、 PlayStation、 Sharp Zaurus、 Windows CE 以及 PocketPC 平台上运行 Python! + +你甚至可以通过诸如 [Kivy](http://kivy.org) 一类的平台来制作可在你的电脑 _以及_ iPhone、iPad 或安卓手机上运行的游戏。 + +### 解释性 + +有关这一特性,需要一些详细的解释。 + +在你使用诸如 C 或 C\++ 等编译语言编写程序时,需要将这些语言的源代码通过编译程序配合其中不同的标记(Flags)与选项,来将它们转换成你的电脑所使用的语言(例如 0 与 1 构成的二进制码)。当你运行这些程序时,链接程序或载入程序将会从硬盘中将程序拷贝至内存中并将其运行。 + +另一方面,Python 不需要将其编译成二进制码。你只需要直接从源代码 _运行_ 该程序。在程序内部,Python 会将源代码转换为称为字节码的中间形式,尔后再转换成你的电脑所使用的语言,并运行它。实际上,这一流程使得 Python 更加易于使用,你不必再担心该如何编译程序,或如何保证适当的库被正确的链接并加载等等步骤。这也同样使得 Python 程序更便携且易于迁移,你只需要将 Python 程序拷贝到另一台电脑便可让它立即开始工作! + +### 面向对象 + +Python 同时支持面向过程编程与面向对象编程。在 _面向过程_ 的编程语言中,程序是由仅仅带有可重用特性的子程序与函数所构建起来的。在 _面向对象_ 的编程语言中,程序是由结合了数据与功能的对象所构建起来的。与 C++ 或 Java 这些大型语言相比,Python 具有其特别的、功能强大又简单的方式来实现面向对象编程。 + +### 可扩展性 + +如果你需要代码的某一重要部分能够快速地运行,或希望算法的某些部分不被公开,你可以在 C 或 C\++ 语言中编写这些程序,然后再将其运用于你的 Python 程序中。 + +### 可嵌入性 + +你可以在你的 C 或 C\++ 程序中嵌入 Python,从而向你的程序用户提供 _脚本_ 功能。 + +### 丰富的库 + +实际上 Python 标准库的规模非常庞大。它能够帮助你完成诸多事情,包括正则表达式、文档生成、单元测试、多线程、数据库、网页浏览器、CGI、FTP、邮件、XML、XML-RPC、HTML、WAV 文件、密码系统、GUI(图形用户界面),以及其它系统依赖型的活动。只需记住,只要安装了 Python,这些功能便随时可用。它们的存在被称作 Python _自备电池(Batteries Included)_ 式的哲学。 + +除了标准库以外,你还可以在 [Python 库索引(Python Package Index)](http://pypi.python.org/pypi) 中发掘许多其它高质量的库。 + +### 总结 + +Python 着实是一门令人心生激动且强大的语言。它得当地结合了性能与功能,使得编写 Python 程序是如此简易又充满乐趣。 + +### Python 3 VS Python 2 + +如果你对“Python 2”与“Python 3”之间的区别不感兴趣你可以略过本段。但务必注意你正在使用的版本。本书是以 Python 3 为对象撰写的。 + +只消记住一旦你正确理解并学习了其中一个版本的 Python,你便可以很容易地理解另一版本的区别,并能快速学习如何使用。困难的是学习如何编程以及理解 Python 语言本身的基础部分。这便是我们在本书中的目标,而一旦你达成了目标,你便可以根据你的实际情况,决定是该使用 Python 2 还是 Python 3。 + +要想了解有关 Python 2 和 Python 3 之间的区别的更多细节,你可以参阅: + +- [The future of Python 2](http://lwn.net/Articles/547191/) +- [Porting Python 2 Code to Python 3](https://docs.python.org/3/howto/pyporting.html) +- [Writing code that runs under both Python2 and 3](https://wiki.python.org/moin/PortingToPy3k/BilingualQuickRef) +- [Supporting Python 3: An in-depth guide](http://python3porting.com) + +### 程序员怎么说 + +或许你在阅读诸如 ESR 等伟大的黑客是如何讨论 Python 时会有些有趣的发现: + +- _埃里克·雷蒙(Eric S. Raymond)_ 是《大教堂和市集(The Cathedral and the Bazaar)》的作者,同时也是 _开放源代码促进会_ 的创始人之一。他曾说[Python 已成为他所喜爱的一门编程语言](http://www.python.org/about/success/esr/)。这篇文章给了我接触 Python 的最先鼓舞。 +- _布鲁斯·埃克尔(Bruce Eckel)_ 是《Java 编程思想(Thinking in Java)》与《C++ 编程思想(Thinking in C++)》的作者。他说没有一种编程语言能像 Python 这样使他更加高产。他说或许 Python 是唯一一门面向程序员且致力于使事情变得更加容易的语言。阅读 [完整采访](http://www.artima.com/intv/aboutme.html) 以了解更多细节。 +- _彼得·诺米格(Peter Norvig)_ 是广为人知的 Lisp 作者,同时也是 Google 公司的搜索质量总监(Director of Search Quality,感谢吉多·范罗苏姆指出这一点)。他说[写 Python 时就好像在写伪代码](https://news.ycombinator.com/item?id=1803815)。他还说 Python 一直是构成 Google 整体的重要部分。你可以通过浏览 [Google Jobs](http://www.google.com/jobs/index.html) 页面并发现“Python 知识”是软件工程师所须具备的一项要求来验证这一说法。 \ No newline at end of file diff --git a/05.installation.md b/05.installation.md new file mode 100644 index 00000000..9e8ab287 --- /dev/null +++ b/05.installation.md @@ -0,0 +1,83 @@ +# 安装 + +我们在本书中提及“Python 3”时,我们指的是任何大于等于 3.5.1 的 Python 发行版。 + +## 在 Windows 中安装 + +访问 https://www.python.org/downloads/ 并下载最新版本的 Python。在本书撰写的时点,最新版本为 Python 3.5.1。 其安装过程与其它 Windows 平台的软件的安装过程无异。 + +注意:请务必确认你勾选了 `Add Python 3.5 to PATH` 选项。 + +若要想改变安装位置,勾选 `Customize installation` 选项,点击 `Next` 后在安装位置中输入 `C:\python35` 。 + +如未勾选相关选项,你可以点击 `Add Python to environment variables` 。它和安装程序第一屏的 `Add Python 3.5 to PATH` 能起到相同效果。 + +你可以选择是否为所有用户安装启动器,这不会产生多大影响。启动器用以切换已安装的不同版本的 Python。 + +如果你的环境变量(Path)未正确设置,可以遵循上述步骤予以修正。否则,请参阅 `在 Windows 中运行 Python 提示符` 。 + +注意:对于那些对编程有所了解的人,如果你熟悉 Docker,可以参阅 [Python in Docker](https://hub.docker.com/\_/python/) 和 [Docker on Windows](https://docs.docker.com/windows/)。 + +### DOS 提示符 + +如果你希望在 Windows 命令行使用 Python,比如 DOS 提示符,你需要设置相应的PATH 环境变量。 + +对于 Windows 2000,XP,2003,点击 `控制面板` → `系统` → `高级` → `环境变量` 。点击 _系统变量_ 选项卡下名为 `PATH` 的变量,选择 `编辑` 并在已存在的字符串末尾添加 `;C:\Python35` (请确保该文件夹确实存在,对于更新版本的 Python 文件夹的名字可能有所不同)。当然,你应该使用恰当的目录名称。 + +对于更古老的 Windows 系统版本,打开文件 `C:\AUTOEXEC.BAT` 并在其中添加一行 `PATH=%PATH%;C:\Python35` ,完成编辑并保存后,你需要重启系统。对于 Windows NT 系统,则对应 `AUTOEXEC.NT` 文件。 + +对于 Windows Vista: + +* 点击开始并选择 `控制面板` 。 +* 点击系统,在右侧你将会看见“浏览你的计算机的基本信息” +* 左侧将由一个任务列表,最后一个即为“高级系统设置”,点击它。 +* `高级` 标签栏下可以看见 `系统属性` 对话框。 +* 在较低位置的名为 `系统变量` 的对话框,向下滚动至变量部分并点击 `编辑` 按钮。 +* 修改你需要改动的变量。 +* 重启系统。Vista 直至重启前都不会应用系统变量环境的改动。 + +对于 Windos 7 与 8: + +* 在桌面右击计算机并选择 `属性` 或点击 `开始` 并选择 `控制面板` → `系统与安全` → `系统` 。点击左侧的 `高级系统设置` 并选择 `高级` 标签。点击底部 `系统变量` 下的 `环境变量` ,找到 `PATH` 属性,将其选中并点击 `编辑` 。 +* 前往变量值的最后一行并添加 `;C:\Python35` (请确保该文件夹确实存在,对于更新版本的 Python 文件夹的名字可能有所不同)至业已存在的部分的后方。当然,你应该使用恰当的目录名称。 +* 如果该变量值为 `%SystemRoot%\system32;` 则在修改后其应变为 `%SystemRoot%\system32;C:\Python35` 。 +* 点击 `确定` 以完成操作。你不需要进行重启,不过你可能需要关闭并重启命令提示符。 + +### 在 Windows 下运行 Python 命令提示符 + +对于 Windows 用户来说,如果你已经正确并恰当地[设置了 `PATH` 变量](05.installation.md#dos-prompt),你可以在命令行中运行解释程序。 + +要想在 Windows 中运行终端,点击开始并点击 `运行` 。在对话中输入 `cmd` 并按下回车键。 + +然后,输入 `python` 以确保其没有任何错误。 + +## 在 Mac OS 下安装 + +对于 Mac OS X 用户,你可以使用 [Homebrew](http://brew.sh) 并通过命令 `brew install python3` 进行安装。 + +要想验证安装是否成功,你可以通过按键 `[Command + Space]` (以启动 Spotlight 搜索),输入 `Terminal` 并按下 `[enter]` 键来启动终端程序。现在,试着运行 `python3` 来确保其没有任何错误。 + +## 在 GNU/Linux 下安装 + +对于 GNU/Linux 用户,你可以使用发行版的包管理器来安装 Python 3,例如在 Debian 与 Ubuntu 平台下,你可以输入命令:`sudo apt-get update && sudo apt-get install python3` 。 + +要想验证安装是否成功,你可以通过打开 `Terminal` 应用或通过按下 `Alt + F2` 组合键并输入 `gnome-terminal` 来启动终端程序。如果这不起作用,请查阅你所使用的的 GNU/Linux 发行版的文档。现在,运行 `python3` 命令来确保其没有任何错误。 + +你会看到在运行命令后 Python 的版本信息显示在屏幕上: + +``` +$ python3 -V +Python 3.5.1 +``` + +附注:`$` 是 Shell 的提示符。根据你电脑所运行的操作系统的设置的不同,它也会有所不同,在之后的内容中我会使用 `$` 符号来代表提示符。 + +注意:输出的内容会因你的电脑而有所不同,其取决于你在你的电脑上安装的 Python 版本。 + +## 总结 + +从现在起,我们将假定你已经在你的系统中安装了 Python。 + +接下来,我们将要撰写我们的第一个 Python 程序。 + +*** diff --git a/06.first_steps.md b/06.first_steps.md new file mode 100644 index 00000000..285f0931 --- /dev/null +++ b/06.first_steps.md @@ -0,0 +1,184 @@ +# 第一步 + +接下来我们将看见如何在 Python 中运行一个传统的“Hello World”程序。本章将会教你如何编写、保存与运行 Python 程序。 + +通过 Python 来运行的你的程序有两种方法——使用交互式解释器提示符或直接运行一个源代码文件。我们将了解如何使用他们二者的功能。 + +## 使用解释器提示符 + +在你的操作系统中打开终端(Terminal)程序(正如我们先前在 [安装](05.installation.md) 章节所讨论过的那样)然后通过输入 `python3` 并按下 `[enter]` 键来打开 Python 提示符(Python Prompt)。 + +当你启动 Python 后,你会看见在你能开始输入内容的地方出现了 `>>>` 。这个被称作 _Python 解释器提示符(Python Interpreter Prompt)_ 。 + +在 Python 解释器提示符,输入: + +```python +print("Hello World") +``` + +在输入完成后按下 `[enter]` 键。你将会看到屏幕上打印出 `Hello World` 字样。 + +下面是一个在 Mac OS X 电脑上你能够看见的结果的示例。有关 Python 软件的细节将会因为你使用的电脑而有所不同,但是从提示符(如 `>>>` )开始部分应该是相同的,而不会受到操作系统的影响。 + +```python +> python3 +Python 3.5.1 (default, Jan 14 2016, 06:54:11) +[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> print("Hello World") +Hello World +``` + +你自然会注意到,Python 会立即给你输出了一行结果!你刚才所输入的便是一句独立的 Python _语句_ 。我们使用 `print` (不必太过惊讶)命令来打印你所提供的信息。在这里,我们提供了文本 `Hello World` ,然后它便被迅速地打印到了屏幕上。 + +### 如何退出解释器提示符 + +如果你正在使用一款 GNU/Linux 或 OS X 上的 Shell 程序,你可以通过按下 `[ctrl + d]` 组合键或是输入 `exit()` (注意:要记住要包含括号 `()`)并敲下 `[enter]` 来退出解释器提示符。 + +如果你使用的是 Windows 命令提示符,可以按下 `[ctrl + z]` 组合键并敲击 `[enter]` 键来退出。 + +## 选择一款编辑器 + +当我们希望运行某些程序时,总不能每次都在解释器提示符中输入我们的程序。因此我们需要将它们保存为文件,从而我们便可以多次地运行这些程序。 + +要想创建我们的 Python 源代码文件,我们需要一款能够让你输入并保存代码的编辑器软件。一款优秀的面向程序员的编辑器能够帮助你的编写源代码文件工作变得轻松得多。故而选择一款编辑器确实至关重要。你要像挑选你想要购买的汽车一样挑选你的编辑器。一款优秀的编辑器能够帮助你更轻松地编写 Python 程序,使你的编程之旅更加舒适,并助你找到一条更加安全且快速的道路到达你的目的地(实现你的目标)。 + +对编辑器的一项最基本要求为 _语法高亮_ ,这一功能能够通过标以不同颜色来帮助你区分 Python 程序中的不同部分,从而能够让你更好 _看清_ 你的程序,并使它的运行模式更加形象化。 + +如果你对应从哪开始还没有概念,我推荐你使用 [PyCharm 教育版](https://www.jetbrains.com/pycharm-edu/) 软件,它在 Windows、Mac OS X、GNU/Linux 上都可以运行。在下一节你能够了解到更多信息。 + +如果你正在使用 Windows 系统,**不要用记事本**——这是一个很糟糕的选择,因为它没有语法加亮功能,同样重要的另一个原因是,它不支持文本缩进功能,这一功能我们之后将会了解它究竟有多重要。而一款好的编辑器能够自动帮你完成这一工作。 + +如果你已是一名经验丰富的程序员,那你一定在用 [Vim](http://www.vim.org) 或 [Emacs](http://www.gnu.org/software/emacs/) 了。无需多言,它们都是最强大的编辑器之一,用它们来编写你的 Python 程序自是受益颇多。我个人用它们来编写了我大部分程序,同时也因此写了一本书《\[Entire Book on Vim]\(\{{ book.vimBookUrl \}})》。 + +或许你有意去花费时间来学习 Vim 或 Emacs,那么我自是强烈推荐你学习它们二者中的一款,它们将在长远意义上对你裨益颇深。当然,正如我先前所推荐的,初学者可以以 PyCharm 开始,从而在此刻专注于学习 Python 而不是编辑器。 + +再此重申,请选择一款合适的编辑器——它能够让编写 Python 程序变得更加有趣且容易。 + +## PyCharm + +[PyCharm 教育版](https://www.jetbrains.com/pycharm-edu/)是一款能够对你编写 Python 程序的工作有所帮助的免费编辑器。 + +当你打开 PyCharm 时,你会看见如下界面,点击 `Create New Project` : + +![当你打开 PyCharm 时](img/pycharm\_open.png) + +选择 `Pure Python` : + +![PyCharm 新项目](img/pycharm\_create\_new\_project.png) + +将你的项目路径位置中的 `untitled` 更改为 `helloworld` ,你所看到的界面细节应该类似于下方这番: + +![PyCharm 项目细节](img/pycharm\_create\_new\_project\_pure\_python.png) + +点击 `Create` 按钮。 + +对侧边栏中的 `helloworld` 右击选中,并选择 `New` -> `Python File` : + +![PyCharm -> New -> Python File](img/pycharm\_new\_python\_file.png) + +你会被要求输入名字,现在输入 `hello` : + +![PyCharm 新文件对话框](img/pycharm\_new\_file\_input.png) + +现在你便可以看见一个新的文件已为你开启: + +![PyCharm hello.py 文件](img/pycharm\_hello\_open.png) + +删除那些已存在的内容,现在由你自己输入以下代码: + +```python +print("hello world") +``` + +现在右击你所输入的内容(无需选中文本),然后点击 `Run 'hello'` 。 + +![PyCharm Run 'hello'](img/pycharm\_run.png) + +此刻你将会看到你的程序所输出的内容(它所打印出来的内容): + +![PyCharm 输出内容](img/pycharm\_output.png) + +嚯!虽然只是刚开始的几个步骤,但从今以后,每当我们要求你创建一个新的文件时,记住只需在 `helloworld` 上右击并选择 -> `New` -> `Python File` 并继续如上所述步骤一般输入内容并运行即可。 + +你可以在 [PyCharm Quickstart](https://www.jetbrains.com/pycharm-educational/quickstart/) 页面找到有关 PyCharm 的更多信息。 + +## Vim + +1. 安装 [Vim](http://www.vim.org)。 + * Mac OS X 应该通过 [HomeBrew](http://brew.sh/) 来安装 `macvim` 包。 + * Windows 用户应该通过 [Vim 官方网站](http://www.vim.org/download.php) 下载“自安装可执行文件”。 + * GNU/Linux 用户应该通过他们使用的发行版的软件仓库获取 Vim。例如 Debian 与 Ubuntu 用户可以安装 `vim` 包。 +2. 安装 [jedi-vim](https://github.com/davidhalter/jedi-vim) 插件为 Vim 增添自动完成功能。 +3. 安装与之相应的 `jedi` Python 包:`pip install -U jedi` + +## Emacs + +1. 安装 [Emacs 24+](http://www.gnu.org/software/emacs/)。 + * Mac OS X 用户应该从 http://emacsformacosx.com 获取 Emacs。 + * Windows 用户应该从 http://ftp.gnu.org/gnu/emacs/windows/ 获取 Emacs。 + * GNU/Linux 用户应该从他们使用的发行版的软件仓库获取 Emacs。如 Debian 和 Ubuntu 用户可以安装 `emacs24` 包。 +2. 安装 [ELPY](https://github.com/jorgenschaefer/elpy/wiki)。 + +## 使用一份源代码文件 + +现在让我们回到编程中来。在你学习一门新的编程语言时有一项传统,你所编写并运行的第一个程序应该是 “Hello World” 程序——它所做的全部工作便是宣言你所运行的“Hello World”这句话。正如西蒙·科泽斯(Simon Cozens,一译西蒙·寇森斯) 所说,这是“向编程之神所称颂的传统咒语,愿他帮助并保佑你更好的学习这门语言”。 + +启动你所选择的编辑器,输入如下程序并将它保存为 `hello.py` 。 + +如果你正在使用 PyCharm,我们已经讨论过[如何从源文件中运行它了](06.first\_steps.md#pycharm)。 + +对于其它编辑器,打开一个新文件名将其命名为 `hello.py` ,然后输入如下内容: + +```python +print("hello world") +``` + +你应当将文件保存到哪里?保存到任何你知道其位置与路径的文件夹。如果你不了解这句话是什么意思,那就创建一个新文件夹并用这一路径来保存并运行你所有的 Python 程序: + +* Mac OS X 上的 `/tmp/py` 。 +* GNU/Linux 上的 `/tmp/py` 。 +* Windows 上的 `C:\\py` 。 + +要想创建上述文件夹(在你正在使用的操作系统上),你可以在终端上使用 `mkdir` 命令,如 `mkdir /tmp/py` 。 + +重要提示:你需要经常确认并确保你为文件赋予了 `.py` 扩展名,例如 `foo.py` 。 + +要想运行你的 Python 程序: + +1. 打开终端窗口(你可查阅先前的 [安装](05.installation.md)章节来了解应该怎么做)。 +2. 使用 `cd` 命令来**改**变**目**录到你保存文件的地方,例如 `cd /tmp/py` 。 +3. 通过输入命令 `python hello.py` 来运行程序。程序的输出结果应如下方所示: + +``` +$ python hello.py +hello world +``` + +![在终端中运行程序的截图](img/terminal\_screenshot.png) + +如果你得到了与上图类似的输出结果,那么恭喜你!——你已经成功运行了你的第一个 Python 程序。你亦已经成功穿过了学习编程的最困难的部分,也就是,开始编写你的第一个程序! + +如果你遭遇了什么错误,请确认是否已经\_正确地\_输入了上面所列出的内容,并尝试重新运行程序。要注意 Python 是区分大小写的,如 `print` 和 `Print` 是不同的——注意前者的 p 是小写的,而后者的 P 是大写的。此外,你需要确保每一行的第一个字符前面都没有任何空格或制表格——我们会在后面了解 [为什么这件事如此重要](07.basics.md#indentation)。 + +**它是如何工作的** + +一款 Python 程序是由 _语句_ 所构成的。在我们的第一个程序中,我们只有一条语句。在这条语句中,我们调用 `print` _语句_ 来搭配我们提供的文本”hello world“。 + +## 获取帮助 + +如果你需要获得 Python 中有关任何函数或语句的快速信息,你可以使用其内置的 `help` 功能。这在使用解释器提示符时十分有用。例如,运行 `help('len')` 命令——这将显示出有关 `len` 函数的帮助,了解其是用来计算项目数量的。 + +小贴士:按下 `q` 键可以退出帮助。 + +类似地,你可以通过此方式获得几乎所有有关 Python 的信息。使用 `help()` 命令来了解有关 `help` 它本身的更多信息吧! + +如果你需要获得有关 `return` 这类运算符的帮助,你需要做的就是将它们放在引号中,就像 `help('return')` 这般,这样 Python 就不会混淆我们正在试图做的事情。 + +## 总结 + +现在,你应该可以轻松地编写、保存并运行 Python 程序了。 + +从此你便成为一名 Python 用户了,现在让我们来学习更多有关 Python 的概念。 + +*** diff --git a/07.basics.md b/07.basics.md new file mode 100644 index 00000000..86bdf262 --- /dev/null +++ b/07.basics.md @@ -0,0 +1,435 @@ +# 基础 + +只是打印出 `hello world` 肯定是不够的,是吗?你会希望做得比这还要多——你想要输入一些内容,操纵它,然后从中得到一些输出出来的内容。我们可以在 Python 中通过使用变量与常量来实现这一目标,在本章中我们还会学习其它的一些概念。[^1] + +## 注释 + +_注释_ 是任何存在于 `#` 号右侧的文字,其主要用作写给程序读者看的笔记。 + +举个例子: + +```python +print('hello world') #注意到 print 是一个函数 +``` + +或者: + +```python +# 注意到 print 是一个函数 +print('hello world') +``` + +你应该在你的程序中尽可能多地使用有用的注释: + +- 解释假设 +- 说明重要的决定 +- 解释重要的细节 +- 说明你想要解决的问题 +- 说明你想要在程序中克服的问题,等等。 + +[*代码会告诉你怎么做,注释会告诉你为何如此。*](http://www.codinghorror.com/blog/2006/12/code-tells-you-how-comments-tell-you-why.html) + +这样做对你的程序的读者来说非常有用,他们可以很容易地理解你的程序是做什么的。请记住,这个人可以是六个月后的你! + +## 字面常量 + +一个字面常量(Literal Constants)[^2]的例子是诸如 `5`、`1.23` 这样的数字,或者是如 `这是一串文本` 或 `This is a string` 这样的文本。 + +用这样的称呼是因为它们是 _字面上的_ [^3]——你用的就是它字面意义上的值或是内容。数字 `2` 总是表示它本身而非其他含义——它是一个 _常量_,因为它的值不能被改变。因此,所有的这些都被称作字面常量。 + +## 数字 + +数字主要分为两种类型——整数(Integers)与浮点数(Floats)。 + +有关整数的例子即 `2`,它只是一个整数。 + +有关浮点数(Floating Point Numbers,在英文中也会简写为 _floats_ )的例子是 `3.23` 或 `52.3E-4`。其中,`E` 表示 10 的幂。在这里,`52.3E-4` 表示 `52.3 * 10^-4`。 + +> **针对有经验的程序员的提示** +> +> 没有单独的 `long` 类型。`int` 类型可以指任何大小的整数。 + +## 字符串 + +一串字符串(String)是 _字符(Characters)_ 的 _序列(Sequence)_。基本上,字符串就是一串词汇。 + +你将会在几乎所有你撰写的 Python 程序中使用字符串,所以对下面的部分你要多上点心。 + +### 单引号 + +你可以使用单引号来指定字符串,例如 `'将我这样框进来'` 或 `'Quote me on this'` 。 + +所有引号内的空间,诸如空格与制表符,都将按原样保留。 + +### 双引号 + +被双引号包括的字符串和被单引号括起的字符串其工作机制完全相同。例如 `"你的名字是?"` 或 `"What's your name?"` 。 + +### 三引号 {#triple-quotes} + +你可以通过使用三个引号——`"""` 或 `'''` 来指定多行字符串。你可以在三引号之间自由地使用单引号与双引号。来看看这个例子: + +```python +'''这是一段多行字符串。这是它的第一行。 +This is the second line. +"What's your name?," I asked. +He said "Bond, James Bond." +''' +``` + +### 字符串是不可变的 + +这意味着一旦你创造了一串字符串,你就不能再改变它。尽管这看起来像是一件坏事,但实际上并非如此。我们将会在稍后展现的多个程序中看到为何这一点不是一个限制。 + +> **针对 C/C++ 程序员的提示** +> +> Python 中没有单独的 `char` 数据类型。它并非切实必要,并且我相信你不会想念它的。 + + + + +> **针对 Perl/PHP 程序员的提示** +> +> 记住单引号括起的字符串和双引号括起的字符串是一样的——它们不存在任何区别。 + +### 格式化方法 + +有时候我们会想要从其他信息中构建字符串。这正是 `format()` 方法大有用武之地的地方。 + +将以下内容保存为文件 `str_format.py` : + +```python +age = 20 +name = 'Swaroop' + +print('{0} was {1} years old when he wrote this book'.format(name, age)) +print('Why is {0} playing with that python?'.format(name)) +``` + +输出: + +``` +$ python str_format.py +Swaroop was 20 years old when he wrote this book +Why is Swaroop playing with that python? +``` + +**它是如何工作的** + +一个字符串可以使用某些特定的格式(Specification),随后,`format` 方法将被调用,使用这一方法中与之相应的参数替换这些格式。 + +在这里要注意我们第一次应用这一方法的地方,此处 `{0}` 对应的是变量 `name`,它是该格式化方法中的第一个参数。与之类似,第二个格式 `{1}` 对应的是变量 `age`,它是格式化方法中的第二个参数。请注意,Python 从 0 开始计数,这意味着索引中的第一位是 0,第二位是 1,以此类推。 + +我们可以通过联立字符串来达到相同的效果: + +```python +name + 'is' +str(age) + 'years old' +``` + +但这样实现是很丑陋的,而且也容易出错。其次,转换至字符串的工作将由 `format` 方法自动完成,而不是如这般需要明确转换至字符串。再次,当使用 `format` 方法时,我们可以直接改动文字而不必与变量打交道,反之亦然。 + +同时还应注意数字只是一个可选选项,所以你同样可以写成: + +```python +age = 20 +name = 'Swaroop' + +print('{} was {} years old when he wrote this book'.format(name, age)) +print('Why is {} playing with that python?'.format(name)) +``` + +这样做同样能得到与前面的程序一样的输出结果。 + +Python 中 `format` 方法所做的事情便是将每个参数值替换至格式所在的位置。这之中可以有更详细的格式,例如: + +```python +# 对于浮点数 '0.333' 保留小数点(.)后三位 +print('{0:.3f}'.format(1.0/3)) +# 使用下划线填充文本,并保持文字处于中间位置 +# 使用 (^) 定义 '___hello___'字符串长度为 11 +print('{0:_^11}'.format('hello')) +# 基于关键词输出 'Swaroop wrote A Byte of Python' +print('{name} wrote {book}'.format(name='Swaroop', book='A Byte of Python')) +``` + +输出: + +``` +0.333 +___hello___ +Swaroop wrote A Byte of Python +``` + +由于我们正在讨论格式问题,就要注意 `print` 总是会以一个不可见的“新一行”字符(`\n`)结尾,因此重复调用 `print`将会在相互独立的一行中分别打印。为防止打印过程中出现这一换行符,你可以通过 `end` 指定其应以空白结尾: + +```python +print('a', end='') +print('b', end='') +``` + +输出结果如下: + +``` +ab +``` + +或者你通过 `end` 指定以空格结尾: + +```python +print('a', end=' ') +print('b', end=' ') +print('c') +``` + +输出结果如下: + +``` +a b c +``` + +### 转义序列 + +想象一下,如果你希望生成一串包含单引号(`'`)的字符串,你应该如何指定这串字符串?例如,你想要的字符串是 `"What's your name?"`。你不能指定 `'What's your name?'`,因为这会使 Python 对于何处是字符串的开始、何处又是结束而感到困惑。所以,你必须指定这个单引号不代表这串字符串的结尾。这可以通过 _转义序列(Escape Sequence)_ 来实现。你通过 `\` 来指定单引号:要注意它可是反斜杠。现在,你可以将字符串指定为 `'What\'s your name?'`。 + +另一种指定这一特别的字符串的方式是这样的: `"What's your name?"` ,如这个例子般使用双引号。类似地, 你必须在使用双引号括起的字符串中对字符串内的双引号使用转义序列。同样,你必须使用转义序列 `\\` 来指定反斜杠本身。 + +如果你想指定一串双行字符串该怎么办?一种方式即使用[如前所述](#triple-quotes)的三引号字符串,或者你可以使用一个表示新一行的转义序列——`\n` 来表示新一行的开始。下面是一个例子: + +```python +'This is the first line\nThis is the second line' +``` + +另一个你应该知道的大有用处的转义序列是制表符:`\t` 。实际上还有很多的转义序列,但我必须只在此展示最重要的一些。 + +还有一件需要的事情,在一个字符串中,一个放置在末尾的反斜杠表示字符串将在下一行继续,但不会添加新的一行。来看看例子: + +```python +"This is the first sentence. \ +This is the second sentence." +``` + +相当于 + +```python +"This is the first sentence. This is the second sentence." +``` + +### 原始字符串 + +如果你需要指定一些未经过特殊处理的字符串,比如转义序列,那么你需要在字符串前增加 `r` 或 `R` 来指定一个 _原始(Raw)_ 字符串[^4]。下面是一个例子: + +```python +r"Newlines are indicated by \n" +``` + +> **针对正则表达式用户的提示** +> +> 在处理正则表达式时应全程使用原始字符串。否则,将会有大量 Backwhacking 需要处理。举例说明的话,反向引用可以通过 `'\\1'` 或 `r'\1' ` 来实现。 + +## 变量 + +如果只使用字面常量很快就会让人感到无聊——我们需要一些能够存储任何信息并且也能操纵它们的方式。这便是 _变量(Variables)_ 登场的时刻。正如其名字所述那般,变量的值是可以变化的,也就是说,你可以用变量来存储任何东西。变量只是你的计算机内存中用以存储信息的一部分。与文字常量不同,你需要通过一些方式来访问这些变量,因此,你需要为它们命名。 + +## 标识符命名 + +变量是标识符的一个例子。_标识符(Identifiers)_ 是为 _某些东西_ 提供的给定名称。在你命名标识符时,你需要遵守以下规则: + +- 第一个字符必须是字母表中的字母(大写 ASCII 字符或小写 ASCII 字符或 Unicode 字符)或下划线(`_`)。 +- 标识符的其它部分可以由字符(大写 ASCII 字符或小写 ASCII 字符或 Unicode 字符)、下划线(`_`)、数字(0~9)组成。 +- 标识符名称区分大小写。例如,`myname` 和 `myName` 并_不_等同。要注意到前者是小写字母 `n` 而后者是大写字母 `N`。 +- _有效_ 的标识符名称可以是 `i` 或 `name_2_3` ,_无效_ 的标识符名称可能是 `2things`,`this is spaced out`,`my-name` 和 `>a1b2_c3`。 + +## 数据类型 + +变量可以将各种形式的值保存为不同的_数据类型(Data Type)_。基本的类型是我们已经讨论过的数字与字符串。在后面的章节中,我们会了解如何通过 [类(Classes)](./14.oop.md#classes) 类创建我们自己的类型。 + +## 对象 + +需要记住的是,Python 将程序中的任何内容统称为 _对象(Object)_。这是一般意义上的说法。我们以“_某某对象(object)_”相称,而非“_某某东西(something)_”。 + +> **针对面向对象编程语言用户的提示:** +> +> Python 是强(Strongly)面向对象的,因为所有的一切都是对象, 包括数字、字符串与函数。 + +接下来我们将看见如何使用变量与字面常量。你需要保存以下案例并试图运行程序。 + +## 如何编写 Python 程序 + +从今以后,保存和运行 Python 程序的标准步骤如下: + +### 对于 PyCharm 用户 + +1. 打开 [PyCharm](./06.first_steps.md#pycharm)。 +2. 以给定的文件名创建新文件。 +3. 输入案例中给出的代码。 +4. 右键并运行当前文件。 + +注意:每当你需要提供 [命令行参数(Command Line Arguments)](./11.modules.md#modules)时,点击 `Run` -> `Edit Configurations` 并在 `Script parameters:` 部分输入相应参数,并点击 `OK` 按钮: + +![PyCharm 命令行参数](./img/pycharm_command_line_arguments.png) + +### 对于其他编辑器用户 + +1. 打开你选择的编辑器。 +2. 输入案例中给出的代码。 +3. 以给定的文件名将其保存成文件。 +4. 在解释器中通过命令 `python program.py` 来运行程序。 + +### 案例:使用变量与字面常量 + +输入并运行以下程序: + +```python +# 文件名:var.py +i = 5 +print(i) +i = i + 1 +print(i) + +s = '''This is a multi-line string. +This is the second line.''' +print(s) +``` + +输出: + +``` +5 +6 +This is a multi-line string. +This is the second line. +``` + +**它是如何工作的** + +下面是这一程序的工作原理。首先,我们使用赋值运算符(`=`)将字面常量数值 `5` 赋值给变量 `i`。这一行被称之为声明语句(Statement)因为其工作正是声明一些在这一情况下应当完成的事情:我们将变量名 `i` 与值 `5` 相连接。然后,我们通过 `print` 语句来打印变量 `i` 所声明的内容,这并不奇怪,只是将变量的值打印到屏幕上。 + +接着,我们将 `1` 加到 `i` 变量所存储的值中,并将得出的结果重新存储进这一变量。然后我们将这一变量打印出来,并期望得到的值应为 `6`。 + +类似地,我们将字面文本赋值给变量 `s`,并将其打印出来。 + +> **针对静态编程语言程序员的提示** +> +> 变量只需被赋予某一值。不需要声明或定义数据类型。 + +## 逻辑行与物理行 + +所谓物理行(Physical Line)是你在编写程序时 _你所看到_ 的内容。所谓逻辑行(Logical Line)是 _Python 所看到_ 的单个语句。Python 会假定每一 _物理行_ 会对应一个 _逻辑行_。 + +有关逻辑行的一个例子是诸如 `print('hello world')` 这样一句语句——如果其本身是一行(正如你在编辑器里所看到的那样),那么它也对应着一行物理行。 + +Python 之中暗含这样一种期望:Python 鼓励每一行使用一句独立语句从而使得代码更加可读。 + +如果你希望在一行物理行中指定多行逻辑行,那么你必须通过使用分号(`;`)来明确表明逻辑行或语句的结束。下面是一个例子: + +```python +i = 5 +print(i) +``` + +实际上等同于 + +```python +i = 5; +print(i); +``` + +同样可以看作 + +```python +i = 5; print(i); +``` + +也与这一写法相同 + +```python +i = 5; print(i) +``` + +然而,我*强烈建议*你**对于每一行物理行最多只写入一行逻辑行**。这个观点就是说你不应该使用分号。实际上,我_从未_在 Python 程序中使用、甚至是见过一个分号。 + +在一类情况下这一方法会颇为有用:如果你有一行非常长的代码,你可以通过使用反斜杠将其拆分成多个物理行。这被称作_显式行连接(Explicit Line Joining)_[^5]: + +```python +s = 'This is a string. \ +This continues the string.' +print(s) +``` + +输出: + +``` +This is a string. This continues the string. +``` + +类似地, + +```python +i = \ +5 +``` + +等同于 + +```python +i = 5 +``` + +在某些情况下,会存在一个隐含的假设,允许你不使用反斜杠。这一情况即逻辑行以括号开始,它可以是方括号或花括号,但不能是右括号。这被称作 *隐式行连接(Implicit Line Joining)*。你可以在后面当我们讨论[列表(List)](./12.data_structures.md#lists)的章节时了解这一点。 + +## 缩进 + +空白区[^6]在 Python 中十分重要。实际上,*空白区在各行的开头非常重要*。这被称作 _缩进(Indentation)_。在逻辑行的开头留下空白区(使用空格或制表符)用以确定各逻辑行的缩进级别,而后者又可用于确定语句的分组。 + +这意味着放置在一起的语句_必须_拥有相同的缩进。每一组这样的语句被称为 *块(block)*。我们将会在后文章节的案例中了解块这一概念是多么重要。 + +有一件事你需要记住:错误的缩进可能会导致错误。下面是一个例子: + +```python +i = 5 +# 下面将发生错误,注意行首有一个空格 + print('Value is', i) +print('I repeat, the value is', i) +``` + +当你运行这一程序时,你将得到如下错误: + +``` + File "whitespace.py", line 3 + print('Value is', i) + ^ +IndentationError: unexpected indent +# 缩进错误:意外缩进 +``` + +你会注意到第二行开头有一个空格。Python 指出的错误信息告诉我们程序的语法是无效的,意即,程序没有被正确地写入。这一信息对你的意义是 _你不能任意开始一个新的语句块_(当然,除非你一直在使用默认的主代码块)。你可以使用新块的情况将会在后面诸如[控制流](./09.control_flow.md#control_flow)等章节加以介绍。 + +> **如何缩进** +> +> 使用四个空格来缩进。这是来自 Python 语言官方的建议。好的编辑器会自动为你完成这一工作。请确保你在缩进中使用数量一致的空格,否则你的程序将不会运行,或引发不期望的行为。 + + + +> **针对静态编程语言程序员的提示** +> +> Python 将始终对块使用缩进,并且绝不会使用大括号。你可以通过运行 `from __future__ import braces` 来了解更多信息。 + +## 总结 + +现在我们已经了解了诸多本质性的细节,我们可以前去了解控制流语句等更多更加有趣的东西。记得一定要充分理解你在本章所阅读的内容。 + + + +--- + +[^1]: 自本章起,书中将出现大量程序源代码内容,在源代码中会包含一些英文语句或者英文注释。为保持源代码整体美观以及避免其它不必要的改动,在代码内容中出现的英文语句将会保持原样,英文注释将酌情翻译。 + +[^2]: “字面常量”原文作 Literal Constants。沈洁元译本译作“字面意义上的常量”。在一些 Python 中文文档中,Literal 译作“字面值”。 + +[^3]: 原文作 literal。 + +[^4]: “原始字符串”原文作 Raw String。沈洁元译本译作“自然字符串”。 + +[^5]: 沈洁元译本译作“明确的行连接”。 + +[^6]: 空白区原文作“Whitespace”,沈洁元译本译作“空白”。它可能被理解成“空格”,但为了与后文的空格(Space)区分,此处取字面意。 diff --git a/08.op_exp.md b/08.op_exp.md new file mode 100644 index 00000000..f79c1ce4 --- /dev/null +++ b/08.op_exp.md @@ -0,0 +1,224 @@ +#运算符与表达式 {#op-exp} + +你所编写的大多数语句(逻辑行)都包含了_表达式(Expressions)_。一个表达式的简单例子便是 `2+3`。表达式可以拆分成运算符(Operators)与操作数(Operands)。 + +_运算符(Operators)_是进行某些操作,并且可以用诸如 `+` 等符号或特殊关键词加以表达的功能。运算符需要一些数据来进行操作,这些数据就被称作_操作数(Operands)_。在上面的例子中 `2` 和 `3` 就是操作数。 + +## 运算符 + +接下来我们将简要了解各类运算符及它们的用法。 + +要记得你可以随时在解释器中对给出的案例里的表达式进行求值。例如要想测试表达式 `2+3`,则可以使用交互式 Python 解释器提示符: + +```python +>>> 2 + 3 +5 +>>> 3 * 5 +15 +>>> +``` + +下面是可用运算符的速览: + +- `+`(加) + - 两个对象相加。 + - `3+5` 则输出 `8`。`'a' + 'b'` 则输出 `'ab'`。 + +- `-`(减) + - 从一个数中减去另一个数,如果第一个操作数不存在,则假定为零。 + - `-5.2` 将输出一个负数,`50 - 24` 输出 `26`。 + +- `*`(乘) + - 给出两个数的乘积,或返回字符串重复指定次数后的结果。 + - `2 * 3` 输出 `6`。`'la' * 3` 输出 `'lalala'`。 + +- `**` (乘方) + - 返回 x 的 y 次方。 + - `3 ** 4` 输出 `81` (即 `3 * 3 * 3 * 3`)。 + +- `/` (除) + - x 除以 y + - `13 / 3` 输出 `4.333333333333333`。 + +- `//` (整除) + - x 除以 y 并对结果_向下_取整至最接近的整数。 + - `13 // 3` 输出 `4`。 + - `-13 // 3` 输出 `-5`。 + +- `%` (取模) + - 返回除法运算后的余数。 + - `13 % 3` 输出 `1`。`-25.5 % 2.25` 输出 `1.5`。 + +- `<<` (左移) + - 将数字的位向左移动指定的位数。(每个数字在内存中以二进制数表示,即 0 和1) + - `2 << 2` 输出 `8`。 `2` 用二进制数表示为 `10`。 + - 向左移 2 位会得到 `1000` 这一结果,表示十进制中的 `8`。 + +- `>>` (右移) + - 将数字的位向右移动指定的位数。 + - `11 >> 1` 输出 `5`。 + - `11` 在二进制中表示为 `1011`,右移一位后输出 `101` 这一结果,表示十进制中的 `5`。 + +- `&` (按位与) + - 对数字进行按位与操作。[^1] + - `5 & 3` 输出 `1`。 + +- `|` (按位或) + - 对数字进行按位或操作。[^2] + - `5 | 3` 输出 `7`。 + +- `^`(按位异或) + - 对数字进行按位异或操作。[^3] + - `5 ^ 3` 输出 `6`。 + +- `~` (按位取反)[^4] + - x 的按位取反结果为 -(x+1)。 + - `~5` 输出 `-6`。有关本例的更多细节可以参阅:http://stackoverflow.com/a/11810203 。 + +- `<` (小于) + - 返回 x 是否小于 y。所有的比较运算符返回的结果均为 `True` 或 `False`。请注意这些名称之中的大写字母。 + - `5 < 3` 输出 `False`,`3 < 6` 输出 `True`。 + - 比较可以任意组成组成链接:`3 < 5 < 7` 返回 `True`。 + +- `>` (大于) + - 返回 x 是否大于 y。 + - `5 > 3` 返回 `True`。如果两个操作数均为数字,它们首先将会被转换至一种共同的类型。否则,它将总是返回 `False`。 + +- `<=` (小于等于) + - 返回 x 是否小于或等于 y。 + - `x = 3; y = 6; x<=y` 返回 `True`。 + +- `>=` (大于等于) + - 返回 x 是否大于或等于 y。 + - `x = 4; y = 3; x>=3` 返回 `True`。 + +- `==` (等于) + - 比较两个对象是否相等。 + - `x = 2; y = 2; x == y` 返回 `True`。 + - `x = 'str'; y = 'stR'; x == y` 返回 `False`。 + - `x = 'str'; y = 'str'; x == y` 返回 `True`。 + +- `!=` (不等于) + - 比较两个对象是否不相等。 + - `x = 2; y = 3; x != y` 返回 `True`。 + +- `not` (布尔“非”)[^5] + - 如果 x 是 `True`,则返回 `False`。如果 x 是 `False`,则返回 `True`。 + - `x = True; not x` 返回 `False`。 + +- `and` (布尔“与”)[^6] + - 如果 x 是 `False`,则 `x and y` 返回 `False`,否则返回 y 的计算值。 + - 当 x 是 `False` 时,`x = False; y = True; x and y` 将返回 `False`。在这一情境中,Python 将不会计算 y,因为它已经了解 and 表达式的左侧是 `False`,这意味着整个表达式都将是 `False` 而不会是别的值。这种情况被称作短路计算(Short-circuit Evaluation)。 + +- `or`(布尔“或”)[^7] + - 如果 x 是 `True`,则返回 `True`,否则它将返回 y 的计算值。 + - `x = Ture; y = False; x or y` 将返回 `Ture`。在这里短路计算同样适用。 + +## 数值运算与赋值的快捷方式 + +一种比较常见的操作是对一个变量进行一项数学运算并将运算得出的结果返回给这个变量,因此对于这类运算通常有如下的快捷表达方式: + +```python +a = 2 +a = a * 3 +``` + +同样也可写作: + +```python +a = 2 +a *= 3 +``` + +要注意到 `变量 = 变量 运算 表达式` 会演变成 `变量 运算 = 表达式`。 + +## 求值顺序[^8] + +如果你有一个诸如 `2 + 3 * 4` 的表达式,是优先完成加法还是优先完成乘法呢?我们的高中数学知识会告诉我们应该先完成乘法。这意味着乘法运算符的优先级要高于加法运算符。 + +下面将给出 Python 中从最低优先级(最少绑定)到最高优先级(最多绑定)的优先级表。这意味着,在给定的表达式中,Python 将优先计算表中位列于后的较高优先级的运算符与表达式。 + +为了保持完整,下表是从 [Python 参考手册](http://docs.python.org/3/reference/expressions.html#operator-precedence) 中引用而来。你最好使用圆括号操作符来对运算符与操作数进行分组,以更加明确地指定优先级。这也能使得程序更加可读。你可以阅读[改变运算顺序](#changing-order-of-evaluation)来了解更多的细节。 + +- `lambda`:Lambda 表达式 +- `if - else` :条件表达式 +- `or`:布尔“或” +- `and`:布尔“与” +- `not x`:布尔“非” +- `in, not in, is, is not, <, <=, >, >=, !=, ==`:比较,包括成员资格测试(Membership Tests)和身份测试(Identity Tests)。 +- `|`:按位或 +- `^`:按位异或 +- `&`:按位与 +- `<<, >>`:移动 +- `+, -`:加与减 +- `*, /, //, %`:乘、除、整除、取余 +- `+x, -x, ~x`:正、负、按位取反 +- `**`:求幂 +- `x[index], x[index:index], x(arguments...), x.attribute`:下标、切片、调用、属性引用 +- `(expressions...), [expressions...], {key: value...}, {expressions...}`:表示绑定或元组、表示列表、表示字典、表示集合 + +我们还没有遇到的运算符将在后面的章节中加以解释。 + +在上表中位列同一行的运算符具有_相同优先级_。例如 `+` 和 `-` 就具有相同的优先级。 + +## 改变运算顺序 {#changing-order-of-evaluation} + +为了使表达式更加易读,我们可以使用括号。举个例子,`2 + (3 * 4)` 自是要比 `2 + 3 * 4` 要更加容易理解,因为后者还要求你要了解运算符的优先级。和其它的一切一样,使用括号同样也要适度(而不要过度),同时亦应不要像 `(2 + (3 * 4))` 这般冗余。 + +使用括号还有一个额外的优点——它能帮助我们改变运算的顺序。同样举个例子,如果你希望在表达式中计算乘法之前应先计算加法,那么你可以将表达式写作 `(2 + 3) * 4`。 + +## 结合性[^9] + +运算符通常由左至右结合。这意味着具有相同优先级的运算符将从左至右的方式依次进行求值。如 `2 + 3 + 4` 将会以 `(2 + 3) +4` 的形式加以计算。 + +## 表达式 + +案例(将其保存为 `expression.py`): + +```python +length = 5 +breadth = 2 + +area = length * breadth +print('Area is', area) +print('Perimeter is', 2 * (length + breadth)) +``` + +输出: + +``` +$ python expression.py +Area is 10 +Perimeter is 14 +``` + +**它是如何工作的** + +矩形的长度(Length)与宽度(Breadth)存储在以各自名称命名的变量中。我们使用它们并借助表达式来计算矩形的面积(Area)与周长(Perimeter)。我们将表达式 `length * breadth` 的结果存储在变量 `area` 中并将其通过使用 `print` 函数打印出来。在第二种情况中,我们直接在 `print` 函数中使用了表达式 `2 * (length + breadth)` 的值。 + +同时,你需要注意到 Python是如何_漂亮地打印出_ 输出结果的。尽管我们没有特别在 `Area is` 和变量 `area` 之间指定空格,Python 会帮我们加上所以我们就能得到一个整洁的输出结果,同时程序也因为这样的处理方式而变得更加易读(因为我们不需要在用以输出的字符串中考虑空格问题)。这便是一个 Python 是如何让程序员的生活变得更加便捷美好的范例。 + +## 总结 + +我们已经了解了如何使用运算符、操作数与表达式——这些是我们构建任何程序的基本块。接下来,我们将看到如何在程序中善加利用这些语句。 + + +---- + +[^1]: 按位与是针对二进制数的操作,指将两个二进制数的每一位都进行比较,如果两个相应的二进位都为 1 则此位为 1,否则为 0。在本例中,`5` 的二进制表达为 `101`,`3` 的二进制表达为 `11`(为补全位数进行按位操作写作 `011`),则按位与操作后的结果为 `001`,对应的十进制数为 `1`。 + +[^2]: 按位或是针对二进制数的操作,指将两个二进制数的每一位都进行比较,如果两个相应的二进位有一个为 1 则此位为 1,否则为 0。在本例中,`101` 与 `011` 进行按位或操作后的结果为 `111`,对应十进制数为 `7`。 + +[^3]: 按位异或是针对二进制数的操作,指将两个二进制数的每一位都进行比较,如果两个相应的二进位不同则此位为 1,相同为 0。在本例中,`101` 与 `011` 进行按位异或操作的结果为 `110`,对应十进制数为 `6`。 + +[^4]: 按位取反也称作“按位取非”或“求非”或“取反”,沈洁元译本译作“按位翻转”,是针对二进制数的操作,指将两个二进制数的每一二进位都进行取反操作,`0` 换成 `1`,`1` 换成 `0`。受篇幅与学识所限,本例具体原理不在此处赘述。读者只需按照给出的公式记忆即可。 + +[^5]: 原文作 Boolean NOT。 + +[^6]: 原文作 Boolean AND。 + +[^7]: 原文作 Boolean OR。 + +[^8]: 原文作 Evaluation Order。 + +[^9]: 原文作 Associativity,沈洁元译本译作“结合规律”。 diff --git a/09.control_flow.md b/09.control_flow.md new file mode 100644 index 00000000..b847a82d --- /dev/null +++ b/09.control_flow.md @@ -0,0 +1,285 @@ +# 控制流 + +截止到现在,在我们所看过的程序中,总是有一系列语句从上到下精确排列,并交由 Python 忠实地执行。如果你想改变这一工作流程,应该怎么做?就像这样的情况:你需要程序作出一些决定,并依据不同的情况去完成不同的事情,例如依据每天时间的不同打印出 '早上好' 'Good Morning' 或 '晚上好' 'Good Evening'? + +正如你可能已经猜测到的那番,这是通过控制流语句来实现的。在 Python 中有三种控制流语句——`if` `for` 和 `while`。 + +## `if` 语句 + +`if` 语句用以检查条件:_如果_ 条件为真(True),我们将运行一块语句(称作 _if-block_ 或 _if 块_),_否则_ 我们将运行另一块语句(称作 _else-block_ 或 _else 块_)。其中 _else_ 从句是可选的。 + +案例(保存为 `if.py`): + +```python +number = 23 +guess = int(input('Enter an integer : ')) + +if guess == number: + # 新块从这里开始 + print('Congratulations, you guessed it.') + print('(but you do not win any prizes!)') + # 新块在这里结束 +elif guess < number: + # 另一代码块 + print('No, it is a little higher than that') + # 你可以在此做任何你希望在该代码块内进行的事情 +else: + print('No, it is a little lower than that') + # 你必须通过猜测一个大于(>)设置数的数字来到达这里。 + +print('Done') +# 这最后一句语句将在 +# if 语句执行完毕后执行。 + +``` + +输出: + +```python +$ python if.py +Enter an integer : 50 +No, it is a little lower than that +Done + +$ python if.py +Enter an integer : 22 +No, it is a little higher than that +Done + +$ python if.py +Enter an integer : 23 +Congratulations, you guessed it. +(but you do not win any prizes!) +Done +``` + +**它是如何工作的** + +在这个程序中,我们根据用户猜测的数字来检查这一数字是否是我们所设置的。我们将变量 `number` 设为任何我们所希望的整数,例如 `23`。然后,我们通过 `input()` 函数来获取用户的猜测数。所谓函数是一种可重复使用的程序。我们将在[下一章](10.functions.md#functions)详细讨论它。 + +我们为内置的 `input` 函数提供一串打印到屏幕上的字符串并等待用户的输入。一旦我们输入了某些内容并按下键盘上的 `enter` 键,`input()` 函数将以字符串的形式返回我们所输入的内容。然后我们通过 `int` 将这个字符串转换成一个整数并将其储存在变量 `guess` 中。实际上,`int` 是一个类(Class),但你现在你所需要知道的就是你可以使用它将一串字符串转换成一个整数(假设这个字符串的文本中含有一个有效的整数)。 + +接下来,我们将用户提供的猜测数与我们所选择的数字进行对比。如果它们相等,我们就打印一条成功信息。在这里要注意到我们使用缩进级别来告诉 Python 哪些语句分别属于哪个块。这便是为什么在 Python 中缩进如此重要。我希望你能够坚持“缩进一致”的原则,你能做到吧? + +另外需要注意的是 `if` 语句在结尾处包含一个冒号——我们借此向 Python 指定接下来会有一块语句在后头。 + +然后,我们检查猜测数是否小于我们选择的数字,如果是,我们将告诉用户他们必须猜一个更高一些的数字。在这里我们使用的是 `elif` 语句,它们实际上将两个相连的 `if else-if else` 语句合并成一句 `if-elif-else` 语句。这能够使程序更加简便,并且可以减少所需要的缩进量。 + +`elif` 和 `else` 同样都必须有一个冒号在其逻辑行的末尾,后面跟着与它们相应的语句块(当然,别忘了恰当的缩进)。 + +你可以在 if 块的 一个 `if` 语句中设置另一个 `if` 语句,并可以如此进行下去——这被称作嵌套的 `if` 语句。 + +要记住 `elif` 和 `else` 部分都是可选的。一个最小规模且有效的 `if` 语句是这样的: + +```python +if True: + print('Yes, it is true') +``` + +当 Python 完整执行了 `if` 语句及与其相关的 `elif` 和 `else` 子句后,它将会移动至包含 `if` 语句的代码块的下一句语句中。在本例中,也就是主代码块(程序开始执行的地方),其下一句语句就是 `print('Done')` 语句。在完成这些工作后,Python 会发现已行至程序末尾并宣告工作的完成。 + +尽管这是一个非常简单的程序,我也一直在其中指出你应该注意的事情。所有的这些都可算是简单易懂(对于那些具有 C/C++ 背景的人来说是相当简单易懂)。不过在开始时它们还是可能会不断吸引你的注意,不断地去在意它们。但经过一些更丰富的操作后你就会习惯它们及其中的逻辑,它们对于你来说将会成为“自然而然”的事情。 + +> **针对 C/C++ 程序员的提示** +> +> Python 中不存在 `switch` 语句。你可以通过使用 `if..elif..else` 语句来实现同样的事情(在某些情况下,使用一部[字典](12.data\_structures.md#dictionary)能够更快速地完成)。 + +## `while` 语句 + +`while` 语句能够让你在条件为真的前提下重复执行某块语句。 `while` 语句是 _循环(Looping)_ 语句的一种。`while` 语句同样可以拥有 `else` 子句作为可选选项。 + +案例(保存为 `while.py`): + +```python +number = 23 +running = True + +while running: + guess = int(input('Enter an integer : ')) + + if guess == number: + print('Congratulations, you guessed it.') + # 这将导致 while 循环中止 + running = False + elif guess < number: + print('No, it is a little higher than that.') + else: + print('No, it is a little lower than that.') +else: + print('The while loop is over.') + # 在这里你可以做你想做的任何事 + +print('Done') +``` + +输出: + +```python +$ python while.py +Enter an integer : 50 +No, it is a little lower than that. +Enter an integer : 22 +No, it is a little higher than that. +Enter an integer : 23 +Congratulations, you guessed it. +The while loop is over. +Done +``` + +**它是如何工作的** + +在这一程序中,我们依旧通过猜数游戏来演示,不过新程序的优点在于能够允许用户持续猜测直至他猜中为止——而无需像我们在上一节中所做的那样,每次猜测都要重新运行程序。这种变化恰到好处地演示了 `while` 语句的作用。 + +首先我们将 `input` 与 `if` 语句移到 `while` 循环之中,并在 while 循环开始前将变量 `running` 设置为 `True`。程序开始时,我们首先检查变量 `running` 是否为 `True`,之后再执行相应的 _while 块_。在这一代码块被执行之后,将会重新对条件进行检查,在本例中也就是 `running` 变量。如果它依旧为 `True`,我们将再次执行 while 块,否则我们将继续执行可选的 else 块,然后进入到下一个语句中。 + +`else` 代码块在 `while` 循环的条件变为 `False` 时开始执行——这个开始的时机甚至可能是在第一次检查条件的时候。如果 `while` 循环中存在一个 `else` 代码块,它将总是被执行,除非你通过 `break` 语句来中断这一循环。 + +`True` 和 `False` 被称作布尔(Boolean)型,你可以将它们分别等价地视为 `1` 与 `0`。 + +> **针对 C/C++ 程序员的提示** +> +> 你可以在 `while` 循环中使用 `else` 从句。 + +## `for` 循环 + +`for...in` 语句是另一种循环语句,其特点是会在一系列对象上进行_迭代(Iterates)_,意即它会遍历序列中的每一个项目。我们将在后面的[序列(Sequences)](12.data\_structures.md#sequence)章节中了解有关它的更多内容。现在你所需要的就是所谓队列就是一系列项目的有序集合。 + +案例(保存为 `for.py`): + +```python +for i in range(1, 5): + print(i) +else: + print('The for loop is over') + +``` + +输出: + +```python +$ python for.py +1 +2 +3 +4 +The for loop is over +``` + +**它是如何工作的** + +在这一程序中,我们打印了一个数字_序列_。我们通过内置的 `range` 函数生成这一数字序列。 + +在这里我们所要做的事情是提供两个数字,而 `range` 将会返回一个数字序列,从第一个数字开始,至第二个数字结束。举个例子,`range(1,5)` 将输出序列 `[1, 2, 3, 4]`。在默认情况下,`range` 将会以 1 逐步递增。如果我们向 `range` 提供第三个数字,则这个数字将成为逐步递增的加数。同样举个例子来说明,`range(1,5,2)` 将会输出 `[1, 3]`。要记住这一序列扩展_直到_第二个数字,也就是说,它_不会_包括第二个数字在内。 + +另外需要注意的是,`range()` 每次只会生成一个数字,如果你希望获得完整的数字列表,要在使用 `range()` 时调用 `list()`。例如下面这样:`list(range(5))` ,它将会返回 `[0, 1, 2, 3, 4]`。有关列表的详细解释将会在 [《数据结构》一章](12.data\_structures.md#data-structures)呈现。 + +然后 `for` 循环就会在这一范围内展开递归——`for i in range(1,5)` 等价于 `for i in [1, 2, 3, 4]`,这个操作将依次将队列里的每个数字(或是对象)分配给 `i`,一次一个,然后以每个 `i` 的值执行语句块。在本例中,我们这一语句块所做的就是打印出这些值。 + +同样要记住,`else` 部分是可选的。当循环中包含他时,它总会在 `for` 循环结束后开始执行,除非程序遇到了 [break](09.control\_flow.md#break-statement) 语句。 + +另一个需要注意的地方是 `for...in` 能在任何队列中工作。在这里,我们有的是通过内置的 `range` 函数生成的一串数字列表,但总体来说我们可以包含任何类型对象的队列!我们将会在后面的章节详细解释这一观念。 + +> **针对 C/C++/Java/C# 程序员的提示** +> +> Python 中的 `for` 循环和 C/C++ 中的 `for` 循环可以说是完全不同。C# 程序员会注意到 Python 中的 `for` 循环与 C# 中的 `foreach` 循环相似。Java 程序员则会注意到它同样与 Java 1.5 中的 `for (int i : IntArray)` 无甚区别。 +> +> 在 C/C++ 中,如果你希望编写 `for (int i = 0; i < 5; i++)`,那么在 Python 你只需要写下 `for i in range(0,5)`。正如你所看到的,Python 中的 `for` 循环将更加简单,更具表现力且更不容易出错。 + +## `break` 语句 + +`break` 语句用以_中断_(Break)循环语句,也就是中止循环语句的执行,即使循环条件没有变更为 `False`,或队列中的项目尚未完全迭代依旧如此。 + +有一点需要尤其注意,如果你 _中断_ 了一个 `for` 或 `while` 循环,任何相应循环中的 `else` 块都将_不会_被执行。 + +案例(保存为 `break.py`): + +```python +while True: + s = input('Enter something : ') + if s == 'quit': + break + print('Length of the string is', len(s)) +print('Done') + +``` + +输出: + +```python +$ python break.py +Enter something : Programming is fun +Length of the string is 18 +Enter something : When the work is done +Length of the string is 21 +Enter something : if you wanna make your work also fun: +Length of the string is 37 +Enter something : use Python! +Length of the string is 11 +Enter something : quit +Done + +``` + +**它是如何工作的** + +在本程序中,我们重复地接受用户的输入内容并打印出每一次输入内容的长度。我们通过检查用户输入的是否是 `quit` 这一特殊条件来判断是否应该终止程序。我们通过_中断_循环并转进至程序末尾来结束这一程序。 + +输入字符串的长度可以通过内置的 `len` 函数来找到。 + +记住,`break` 语句同样可以适用于 `for` 循环。 + +**Swaroop 的诗意 Python** + +我所使用的输入内容是一首我所写的小诗: + +``` +Programming is fun +When the work is done +if you wanna make your work also fun: + use Python! +``` + +## `continue` 语句 + +`continue` 语句用以告诉 Python 跳过当前循环块中的剩余语句,并_继续_该循环的下一次迭代。 + +案例(保存为 `continue.py`): + +```python +while True: + s = input('Enter something : ') + if s == 'quit': + break + if len(s) < 3: + print('Too small') + continue + print('Input is of sufficient length') + # 自此处起继续进行其它任何处理 + +``` + +输出: + +```python +$ python continue.py +Enter something : a +Too small +Enter something : 12 +Too small +Enter something : abc +Input is of sufficient length +Enter something : quit + +``` + +**它是如何工作的** + +在本程序中,我们接受来自用户的输入内容,但是只有在输入的字符串其长至少 3 字符我们才会对其进行处理。为此,我们使用内置的 `len` 函数和来获取字符串的长度,如果其长度小于 3,我们便通过使用 `continue` 语句跳过代码块中的其余语句。否则,循环中的剩余语句将被执行,并在此处进行我们所希望的任何类型的处理。 + +要注意 `continue` 语句同样能用于 `for` 循环。 + +## 总结 + +我们已经了解了三种控制流语句——`if`,`while` 和 `for` ——及其相关的 `break` 与 `continue` 语句是如何工作的。这些语句是 Python 中一些最常用的部分,因此,习惯去使用它们是必要的。 + +接下来,我们将了解如何创建并使用函数。 diff --git a/10.functions.md b/10.functions.md new file mode 100644 index 00000000..2a40d4ac --- /dev/null +++ b/10.functions.md @@ -0,0 +1,380 @@ +# 函数 + +函数(Functions)是指可重复使用的程序片段。它们允许你为某个代码块赋予名字,允许你通过这一特殊的名字在你的程序任何地方来运行代码块,并可重复任何次数。这就是所谓的\*调用(Calling)\*函数。我们已经使用过了许多内置的函数,例如 `len` 和 `range`。 + +函数概念可能是在任何复杂的软件(无论使用的是何种编程语言)中_最_重要的构建块,所以我们接下来将在本章中探讨有关函数的各个方面。 + +函数可以通过关键字 `def` 来定义。这一关键字后跟一个函数的_标识符_名称,再跟一对圆括号,其中可以包括一些变量的名称,再以冒号结尾,结束这一行。随后而来的语句块是函数的一部分。下面的案例将会展示出这其实非常简单: + +案例(保存为 `function1.py`): + +```python +def say_hello(): + # 该块属于这一函数 + print('hello world') +# 函数结束 + +say_hello() # 调用函数 +say_hello() # 再次调用函数 + +``` + +输出: + +```python +$ python function1.py +hello world +hello world + +``` + +**它是如何工作的** + +我们以上文解释过的方式定义名为 `say_hello` 的函数。这个函数不使用参数,因此在括号中没有声明变量。函数的参数只是输入到函数之中,以便我可以传递不同的值给它,并获得相应的结果。 + +要注意到我们可以两次调用相同的函数,这意味着我们不必重新把代码再写一次。 + +## 函数参数 + +函数可以获取参数,这个参数的值由你所提供,借此,函数便可以利用这些值来_做_一些事情。这些参数与变量类似,这些变量的值在我们调用函数时已被定义,且在函数运行时均已赋值完成。 + +函数中的参数通过将其放置在用以定义函数的一对圆括号中指定,并通过逗号予以分隔。当我们调用函数时,我们以同样的形式提供需要的值。要注意在此使用的术语——在定义函数时给定的名称称作\_“形参”(Parameters)_,在调用函数时你所提供给函数的值称作_“实参”(Arguments)\_。 + +案例(保存为 `function_param.py`): + +```python +def print_max(a, b): + if a > b: + print(a, 'is maximum') + elif a == b: + print(a, 'is equal to', b) + else: + print(b, 'is maximum') + +# 直接传递字面值 +print_max(3, 4) + +x = 5 +y = 7 + +# 以参数的形式传递变量 +print_max(x, y) + +``` + +输出: + +```python +$ python function_param.py +4 is maximum +7 is maximum + +``` + +**它是如何工作的** + +在这里,我们将函数命名为 `print_max` 并使用两个参数分别称作 `a` 和 `b`。我们使用一个简单的 `if...else` 语句来找出更大的那个数,并将它打印出来。 + +第一次调用函数 `print_max` 时,我们以实参的形式直接向函数提供这一数字。在第二次调用时,我们将变量作为实参来调用函数。`print_max(x, y)` 将使得实参 `x` 的值将被赋值给形参 `a`,而实参 `y` 的值将被赋值给形参 `b`。在两次调用中,`print_max` 都以相同的方式工作。 + +## 局部变量 + +当你在一个函数的定义中声明变量时,它们不会以任何方式与身处函数之外但具有相同名称的变量产生关系,也就是说,这些变量名只存在于函数这一_局部(Local)_。这被称为变量的_作用域(Scope)_。所有变量的作用域是它们被定义的块,从定义它们的名字的定义点开始。 + +案例(保存为 `function_local.py`): + +```python +x = 50 + + +def func(x): + print('x is', x) + x = 2 + print('Changed local x to', x) + + +func(x) +print('x is still', x) + +``` + +输出: + +```python +$ python function_local.py +x is 50 +Changed local x to 2 +x is still 50 + +``` + +**它是如何工作的** + +当我们第一次打印出存在于函数块的第一行的名为 `x` 的值时,Python 使用的是在函数声明之上的主代码块中声明的这一参数的值。 + +接着,我们将值 `2` 赋值给 `x`。`x` 是我们这一函数的局部变量。因此,当我们改变函数中 `x` 的值的时候,主代码块中的 `x` 则不会受到影响。 + +随着最后一句 `print` 语句,我们展示出主代码块中定义的 `x` 的值,由此确认它实际上不受先前调用的函数中的局部变量的影响。 + +## `global` 语句 + +如果你想给一个在程序顶层的变量赋值(也就是说它不存在于任何作用域中,无论是函数还是类),那么你必须告诉 Python 这一变量并非局部的,而是\*全局(Global)\*的。我们需要通过 `global` 语句来完成这件事。因为在不使用 `global` 语句的情况下,不可能为一个定义于函数之外的变量赋值。 + +你可以使用定义于函数之外的变量的值(假设函数中没有具有相同名字的变量)。然而,这种方式不会受到鼓励而且应该避免,因为它对于程序的读者来说是含糊不清的,无法弄清楚变量的定义究竟在哪。而通过使用 `global` 语句便可清楚看出这一变量是在最外边的代码块中定义的。 + +案例(保存为 `function_global.py`): + +```python +x = 50 + + +def func(): + global x + + print('x is', x) + x = 2 + print('Changed global x to', x) + + +func() +print('Value of x is', x) + +``` + +输出: + +```python +$ python function_global.py +x is 50 +Changed global x to 2 +Value of x is 2 + +``` + +**它是如何工作的** + +`global` 语句用以声明 `x` 是一个全局变量——因此,当我们在函数中为 `x` 进行赋值时,这一改动将影响到我们在主代码块中使用的 `x` 的值。 + +你可以在同一句 `global` 语句中指定不止一个的全局变量,例如 `global x, y, z`。 + +## 默认参数值 + +对于一些函数来说,你可能为希望使一些参数_可选_并使用默认的值,以避免用户不想为他们提供值的情况。默认参数值可以有效帮助解决这一情况。你可以通过在函数定义时附加一个赋值运算符(`=`)来为参数指定默认参数值。 + +要注意到,默认参数值应该是常数。更确切地说,默认参数值应该是不可变的——这将在后面的章节中予以更详细的解释。就目前来说,只要记住就行了。 + +案例(保存为 `function_default.py`): + +```python +def say(message, times=1): + print(message * times) + +say('Hello') +say('World', 5) + +``` + +输出: + +``` +$ python function_default.py +Hello +WorldWorldWorldWorldWorld + +``` + +**它是如何工作的** + +名为 `say` 的函数用以按照给定的次数打印一串字符串。如果我们没有提供一个数值,则将按照默认设置,只打印一次字符串。我们通过为参数 `times` 指定默认参数值 `1` 来实现这一点。 + +在第一次使用 `say` 时,我们只提供字符串因而函数只会将这个字符串打印一次。在第二次使用 `say` 时,我们既提供了字符串,同时也提供了一个参数 `5`,声明我们希望_说(Say)_这个字符串五次。 + +> _注意_ +> +> 只有那些位于参数列表末尾的参数才能被赋予默认参数值,意即在函数的参数列表中拥有默认参数值的参数不能位于没有默认参数值的参数之前。 +> +> 这是因为值是按参数所处的位置依次分配的。举例来说,`def func(a, b=5)` 是有效的,但 `def func(a=5, b)` 是_无效的_。 + +## 关键字参数 + +如果你有一些具有许多参数的函数,而你又希望只对其中的一些进行指定,那么你可以通过命名它们来给这些参数赋值——这就是_关键字参数(Keyword Arguments)_——我们使用命名(关键字)而非位置(一直以来我们所使用的方式)来指定函数中的参数。 + +这样做有两大优点——其一,我们不再需要考虑参数的顺序,函数的使用将更加容易。其二,我们可以只对那些我们希望赋予的参数以赋值,只要其它的参数都具有默认参数值。 + +案例(保存为 `function_keyword.py`): + +```python +def func(a, b=5, c=10): + print('a is', a, 'and b is', b, 'and c is', c) + +func(3, 7) +func(25, c=24) +func(c=50, a=100) + +``` + +输出: + +```python +$ python function_keyword.py +a is 3 and b is 7 and c is 10 +a is 25 and b is 5 and c is 24 +a is 100 and b is 5 and c is 50 + +``` + +**它是如何工作的** + +名为 `func` 的函数有一个没有默认参数值的参数,后跟两个各自带有默认参数值的参数。 + +在第一次调用函数时,`func(3, 7)`,参数 `a` 获得了值 `3`,参数 `b` 获得了值 `7`,而 `c` 获得了默认参数值 `10`。 + +在第二次调用函数时,`func(25, c=24)`,由于其所处的位置,变量 `a` 首先获得了值 25。然后,由于命名——即关键字参数——指定,变量 `c` 获得了值 `24`。变量 `b` 获得默认参数值 `5`。 + +在第三次调用函数时,`func(c=50, a=100)`,我们全部使用关键字参数来指定值。在这里要注意到,尽管 `a` 在 `c` 之前定义,但我们还是在变量 `a` 之前指定了变量 `c`。 + +## 可变参数 + +有时你可能想定义的函数里面能够有\_任意\_数量的变量,也就是参数数量是可变的,这可以通过使用星号来实现(将下方案例保存为 `function_varargs.py`): + +```python +def total(a=5, *numbers, **phonebook): + print('a', a) + + #遍历元组中的所有项目 + for single_item in numbers: + print('single_item', single_item) + + #遍历字典中的所有项目 + for first_part, second_part in phonebook.items(): + print(first_part,second_part) + +print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560)) + +``` + +输出: + +```python +$ python function_varargs.py +a 10 +single_item 1 +single_item 2 +single_item 3 +Inge 1560 +John 2231 +Jack 1123 +None + +``` + +**它是如何工作的** + +当我们声明一个诸如 `*param` 的星号参数时,从此处开始直到结束的所有位置参数(Positional Arguments)都将被收集并汇集成一个称为“param”的元组(Tuple)。 + +类似地,当我们声明一个诸如 `**param` 的双星号参数时,从此处开始直至结束的所有关键字参数都将被收集并汇集成一个名为 `param` 的字典(Dictionary)。 + +我们将在[后面的章节](data\_structures.md#data-structures)探索有关元组与字典的更多内容。 + +## `return` 语句 + +`return` 语句用于从函数中_返回_,也就是中断函数。我们也可以选择在中断函数时从函数中_返回一个值_。 + +案例(保存为 `function_return.py`): + +```python +def maximum(x, y): + if x > y: + return x + elif x == y: + return 'The numbers are equal' + else: + return y + +print(maximum(2, 3)) + +``` + +输出: + +``` +$ python function_return.py +3 + +``` + +_它是如何工作的_ + +`maximum` 函数将会返回参数中的最大值,在本例中是提供给函数的数值。它使用一套简单的 `if...else` 语句来找到较大的那个值并将其_返回_。 + +要注意到如果 `return` 语句没有搭配任何一个值则代表着 `返回 None`。`None` 在 Python 中一个特殊的类型,代表着虚无。举个例子, 它用于指示一个变量没有值,如果有值则它的值便是 `None(虚无)`。 + +每一个函数都在其末尾隐含了一句 `return None`,除非你写了你自己的 `return` 语句。你可以运行 `print(some_function())`,其中 `some_function` 函数不使用 `return` 语句,就像这样: + +```python +def some_function(): + pass +``` + +Python 中的 `pass` 语句用于指示一个没有内容的语句块。 + +> 提示:有一个名为 `max` 的内置函数已经实现了“找到最大数”这一功能,所以尽可能地使用这一内置函数。 + +## DocStrings + +Python 有一个甚是优美的功能称作_文档字符串(Documentation Strings)_,在称呼它时通常会使用另一个短一些的名字_docstrings_。DocStrings 是一款你应当使用的重要工具,它能够帮助你更好地记录程序并让其更加易于理解。令人惊叹的是,当程序实际运行时,我们甚至可以通过一个函数来获取文档! + +案例(保存为 `function_docstring.py`): + +```python +def print_max(x, y): + '''打印两个数值中的最大数。 + + 这两个数都应该是整数''' + # 如果可能,将其转换至整数类型 + x = int(x) + y = int(y) + + if x > y: + print(x, 'is maximum') + else: + print(y, 'is maximum') + +print_max(3, 5) +print(print_max.__doc__) + +``` + +输出: + +``` +$ python function_docstring.py +5 is maximum +打印两个数值中的最大数。 + + 这两个数都应该是整数 + +``` + +**它是如何工作的** + +函数的第一行逻辑行中的字符串是该函数的 _文档字符串(DocString)_。这里要注意文档字符串也适用于后面相关章节将提到的[模块(Modules)](11.modules.md#modules)与[类(Class)](14.oop.md#oop) 。 + +该文档字符串所约定的是一串多行字符串,其中第一行以某一大写字母开始,以句号结束。第二行为空行,后跟的第三行开始是任何详细的解释说明。在此_强烈建议_你在你所有重要功能的所有文档字符串中都遵循这一约定。 + +我们可以通过使用函数的 `__doc__`(注意其中的_双下划綫_)属性(属于函数的名称)来获取函数 `print_max` 的文档字符串属性。只消记住 Python 将_所有东西_都视为一个对象,这其中自然包括函数。我们将在后面的[类(Class)](14.oop.md#oop)章节讨论有关对象的更多细节。 + +如果你曾使用过 Python 的 `help()` 函数,那么你应该已经了解了文档字符串的用途了。它所做的便是获取函数的 `__doc__` 属性并以一种整洁的方式将其呈现给你。你可以在上方的函数中尝试一下——只需在程序中包含 `help(print_max)` 就行了。要记住你可以通过按下 `q` 键来退出 `help`。 + +自动化工具可以以这种方式检索你的程序中的文档。因此,我_强烈推荐_你为你编写的所有重要的函数配以文档字符串。你的 Python 发行版中附带的 `pydoc` 命令与 `help()` 使用文档字符串的方式类似。 + +## 总结 + +我们已经了解了许多方面的函数,但我们依旧还未覆盖到所有类型的函数。不过,我们已经覆盖到了大部分你每天日常使用都会使用到的 Python 函数。 + +接下来,我们将了解如何创建并使用 Python 模块。 + +*** + +1. 原文作 Local Varibles。 +2. 原文作 VarArgs Parameters,VarArgs 来自于英文“可变的”“自变量(一译变元,台译引数,也可以理解成参数)”两个英文单词的结合,即 **Var**iable **Arg**uments。 diff --git a/11.modules.md b/11.modules.md new file mode 100644 index 00000000..07a8364b --- /dev/null +++ b/11.modules.md @@ -0,0 +1,266 @@ +# 模块 + +在上一章,你已经了解了如何在你的程序中通过定义一次函数工作来重用代码。那么如果你想在你所编写的别的程序中重用一些函数的话,应该怎么办?正如你可能想象到的那样,答案是模块(Modules)。 + +编写模块有很多种方法,其中最简单的一种便是创建一个包含函数与变量、以 `.py` 为后缀的文件。 + +另一种方法是使用撰写 Python 解释器本身的本地语言来编写模块。举例来说,你可以使用 [C 语言](http://docs.python.org/3/extending/)来撰写 Python 模块,并且在编译后,你可以通过标准 Python 解释器在你的 Python 代码中使用它们。 + +一个模块可以被其它程序_导入_并运用其功能。我们在使用 Python 标准库的功能时也同样如此。首先,我们要了解如何使用标准库模块。 + +案例 (保存为 `module_using_sys.py`): + +```python +import sys + +print('The command line arguments are:') +for i in sys.argv: + print(i) + +print('\n\nThe PYTHONPATH is', sys.path, '\n') + +``` + +输出: + +```python +$ python module_using_sys.py we are arguments +The command line arguments are: +module_using_sys.py +we +are +arguments + + +The PYTHONPATH is ['/tmp/py', +# many entries here, not shown here +'/Library/Python/2.7/site-packages', +'/usr/local/lib/python2.7/site-packages'] + +``` + +**它是如何工作的** + +首先,我们通过 `import` 语句_导入_ `sys` 模块。基本上,这句代码将转化为我们告诉 Python 我们希望使用这一模块。`sys` 模块包含了与 Python 解释器及其环境相关的功能,也就是所谓的_系统_功能(_sys_tem)。 + +当 Python 运行 `import sys` 这一语句时,它会开始寻找 `sys` 模块。在这一案例中,由于其是一个内置模块,因此 Python 知道应该在哪里找到它。 + +如果它不是一个已编译好的模块,即用 Python 编写的模块,那么 Python 解释器将从它的 `sys.path` 变量所提供的目录中进行搜索。如果找到了对应模块,则该模块中的语句将在开始运行,并_能够_为你所使用。在这里需要注意的是,初始化工作只需在我们_第一次_导入模块时完成。 + +`sys` 模块中的 `argv` 变量通过使用点号予以指明,也就是 `sys.argv` 这样的形式。它清晰地表明了这一名称是 `sys` 模块的一部分。这一处理方式的另一个优点是这个名称不会与你程序中的其它任何一个 `argv` 变量冲突。 + +`sys.argv` 变量是一系列字符串的_列表(List)_(列表将在[后面的章节](12.data\_structures.md#data-structures)予以详细解释)。具体而言,`sys.argv` 包含了\*命令行参数(Command Line Arguments)\*这一列表,也就是使用命令行传递给你的程序的参数。 + +如果你正在使用一款 IDE 来编写并运行这些程序,请在程序菜单中寻找相关指定命令行参数的选项。 + +在这里,当我们运行 `python module_using_sys.py we are arguments` 时,我们通过 `python` 命令来运行 `module_using_sys.py` 模块,后面的内容则是传递给程序的参数。 Python 将命令行参数存储在 `sys.argv` 变量中供我们使用。 + +在这里要记住的是,运行的脚本名称在 `sys.argv` 的列表中总会位列第一。因此,在这一案例中我们将会有如下对应关系:`'module_using_sys.py'` 对应 `sys.argv[0]`,`'we'` 对应 `sys.argv[1]`,`'are'` 对应 `sys.argv[2]`,`'arguments'` 对应 `sys.argv[3]`。要注意到 Python 从 0 开始计数,而不是 1。 + +`sys.path` 内包含了导入模块的字典名称列表。你能观察到 `sys.path` 的第一段字符串是空的——这一空字符串代表当前目录也是 `sys.path` 的一部分,它与 `PYTHONPATH` 环境变量等同。这意味着你可以直接导入位于当前目录的模块。否则,你必须将你的模块放置在 `sys.path` 内所列出的目录中。 + +另外要注意的是当前目录指的是程序启动的目录。你可以通过运行 `import os; print(os.getcwd())` 来查看你的程序目前所处在的目录。 + +## 按字节码编译的 .pyc 文件 {#pyc} + +导入一个模块是一件代价高昂的事情,因此 Python 引入了一些技巧使其能够更快速的完成。其中一种方式便是创建\*按字节码编译的(Byte-Compiled)\*文件,这一文件以 `.pyc` 为其扩展名,是将 Python 转换成中间形式的文件(还记得[《介绍》](04.about\_python.md#interpreted)一章中介绍的 Python 是如何工作的吗?)。这一 `.pyc` 文件在你下一次从其它不同的程序导入模块时非常有用——它将更加快速,因为导入模块时所需要的一部分处理工作已经完成了。同时,这些按字节码编译的文件是独立于运行平台的。 + +注意:这些 `.pyc` 文件通常会创建在与对应的 `.py` 文件所处的目录中。如果 Python 没有相应的权限对这一目录进行写入文件的操作,那么 `.pyc` 文件将\_不会\_被创建。 + +## `from..import` 语句 + +如果你希望直接将 `argv` 变量导入你的程序(为了避免每次都要输入 `sys.`),那么你可以通过使用 `from sys import argv` 语句来实现这一点。 + +> \*\*警告:\*\*一般来说,你应该尽量_避免_使用 `from...import` 语句,而去使用 `import` 语句。这是为了避免在你的程序中出现名称冲突,同时也为了使程序更加易读。 + +案例: + +```python +from math import sqrt +print("Square root of 16 is", sqrt(16)) +``` + +## 模块的 `__name__` + +每个模块都有一个名称,而模块中的语句可以找到它们所处的模块的名称。这对于确定模块是独立运行的还是被导入进来运行的这一特定目的来说大为有用。正如先前所提到的,当模块第一次被导入时,它所包含的代码将被执行。我们可以通过这一特性来使模块以不同的方式运行,这取决于它是为自己所用还是从其它从的模块中导入而来。这可以通过使用模块的 `__name__` 属性来实现。 + +案例(保存为 `module_using_name.py`): + +```python +if __name__ == '__main__': + print('This program is being run by itself') +else: + print('I am being imported from another module') + +``` + +输出: + +```python +$ python module_using_name.py +This program is being run by itself + +$ python +>>> import module_using_name +I am being imported from another module +>>> + +``` + +**它是如何工作的** + +每一个 Python 模块都定义了它的 `__name__` 属性。如果它与 `__main__` 属性相同则代表这一模块是由用户独立运行的,因此我们便可以采取适当的行动。 + +## 编写你自己的模块 + +编写你自己的模块很简单,这其实就是你一直在做的事情!这是因为每一个 Python 程序同时也是一个模块。你只需要保证它以 `.py` 为扩展名即可。下面的案例会作出清晰的解释。 + +案例(保存为 `mymodule.py`): + +```python +``` + +上方所呈现的就是一个简单的_模块_。正如你所看见的,与我们一般所使用的 Python 的程序相比其实并没有什么特殊的区别。我们接下来将看到如何在其它 Python 程序中使用这一模块。 + +要记住该模块应该放置于与其它我们即将导入这一模块的程序相同的目录下,或者是放置在 `sys.path` 所列出的其中一个目录下。 + +另一个模块(保存为 `mymodule_demo.py`): + +```python +import mymodule + +mymodule.say_hi() +print('Version', mymodule.__version__) + +``` + +输出: + +```python +$ python mymodule_demo.py +Hi, this is mymodule speaking. +Version 0.1 + +``` + +**它是如何工作的** + +你会注意到我们使用相同的点符来访问模块中的成员。Python 很好地重用了其中的符号,这充满了“Pythonic”式的气息,这使得我们可以不必学习新的方式来完成同样的事情。 + +下面是一个使用 `from...import` 语法的范本(保存为 `mymodule_demo2.py`): + +```python +from mymodule import say_hi, __version__ + +say_hi() +print('Version', __version__) +``` + +`mymodule_demo2.py` 所输出的内容与 `mymodule_demo.py` 所输出的内容是一样的。 + +在这里需要注意的是,如果导入到 mymodule 中的模块里已经存在了 `__version__` 这一名称,那将产生冲突。这可能是因为每个模块通常都会使用这一名称来声明它们各自的版本号。因此,我们大都推荐最好去使用 `import` 语句,尽管这会使你的程序变得稍微长一些。 + +你还可以使用: + +```python +from mymodule import * +``` + +这将导入诸如 `say_hi` 等所有公共名称,但不会导入 `__version__` 名称,因为后者以双下划线开头。 + +> \*\*警告:\*\*要记住你应该避免使用 import \* 这种形式,即 `from mymodule import *` 。 + +> **Python 之禅** +> +> Python 的一大指导原则是“明了胜过晦涩”。你可以通过在 Python 中运行 `import this` 来了解更多内容。 + +## `dir` 函数 + +内置的 `dir()` 函数能够返回由对象所定义的名称列表。 如果这一对象是一个模块,则该列表会包括函数内所定义的函数、类与变量。 + +该函数接受参数。 如果参数是模块名称,函数将返回这一指定模块的名称列表。 如果没有提供参数,函数将返回当前模块的名称列表。 + +案例: + +```python +$ python +>>> import sys + +# 给出 sys 模块中的属性名称 +>>> dir(sys) +['__displayhook__', '__doc__', +'argv', 'builtin_module_names', +'version', 'version_info'] +# 此处只展示部分条目 + +# 给出当前模块的属性名称 +>>> dir() +['__builtins__', '__doc__', +'__name__', '__package__','sys'] + +# 创建一个新的变量 'a' +>>> a = 5 + +>>> dir() +['__builtins__', '__doc__', '__name__', '__package__', 'a'] + +# 删除或移除一个名称 +>>> del a + +>>> dir() +['__builtins__', '__doc__', '__name__', '__package__'] +``` + +**它是如何工作的** + +首先我们看到的是 `dir` 在被导入的 `sys` 模块上的用法。我们能够看见它所包含的一个巨大的属性列表。 + +随后,我们以不传递参数的形式使用 `dir` 函数。在默认情况下,它将返回当前模块的属性列表。要注意到被导入模块的列表也会是这一列表的一部分。 + +给了观察 `dir` 函数的操作,我们定义了一个新的变量 `a` 并为其赋予了一个值,然后在检查 `dir` 返回的结果,我们就能发现,同名列表中出现了一个新的值。我们通过 `del` 语句移除了一个变量或是属性,这一变化再次反映在 `dir` 函数所处的内容中。 + +关于 `del` 的一个小小提示——这一语句用于_删除_一个变量或名称,当这一语句运行后,在本例中即 `del a`,你便不再能访问变量 `a`——它将如同从未存在过一般。 + +要注意到 `dir()` 函数能对_任何_对象工作。例如运行 `dir(str)` 可以访问 `str`(String,字符串)类的属性。 + +同时,还有一个 [`vars()`](http://docs.python.org/3/library/functions.html#vars) 函数也可以返回给你这些值的属性,但只是可能,它并不能针对所有类都能正常工作。 + +## 包 + +现在,你必须开始遵守用以组织你的程序的层次结构。变量通常位于函数内部,函数与全局变量通常位于模块内部。如果你希望组织起这些模块的话,应该怎么办?这便是包(Packages)应当登场的时刻。 + +包是指一个包含模块与一个特殊的 `__init__.py` 文件的文件夹,后者向 Python 表明这一文件夹是特别的,因为其包含了 Python 模块。 + +让我们这样设想:你想创建一个名为“world”的包,其中还包含着 “asia”、“africa”等其它子包,同时这些子包都包含了诸如“india”、 “madagascar”等模块。 + +下面是你会构建出的文件夹的结构: + +``` +- / + - world/ + - __init__.py + - asia/ + - __init__.py + - india/ + - __init__.py + - foo.py + - africa/ + - __init__.py + - madagascar/ + - __init__.py + - bar.py +``` + +包是一种能够方便地分层组织模块的方式。你将在 [标准库](17.stdlib.md#stdlib) 中看到许多有关于此的实例。 + +## 总结 + +如同函数是程序中的可重用部分那般,模块是一种可重用的程序。包是用以组织模块的另一种层次结构。Python 所附带的标准库就是这样一组有关包与模块的例子。 + +我们已经了解了如何使用这些模块并创建你自己的模块。 + +接下来,我们将学习一些有趣的概念,它们被称作数据结构。 + +*** + +1. 原文作 Explicit is better than Implicit,如果使用前面章节出现过的术语概念,也可理解为“显式胜过隐式”。 diff --git a/12.data_structures.md b/12.data_structures.md new file mode 100644 index 00000000..ec6a035b --- /dev/null +++ b/12.data_structures.md @@ -0,0 +1,443 @@ +# 数据结构 + +数据结构(Data Structures)基本上人如其名——它们只是一种_结构_,能够将一些_数据_聚合在一起。换句话说,它们是用来存储一系列相关数据的集合。 + +Python 中有四种内置的数据结构——_列表(List)、元组(Tuple)、字典(Dictionary)和集合(Set)_。我们将了解如何使用它们,并利用它们将我们的编程之路变得更加简单。 + +## 列表 + +`列表` 是一种用于保存一系列有序项目的集合,也就是说,你可以利用列表保存一串项目的_序列_。想象起来也不难,你可以想象你有一张购物清单,上面列出了需要购买的商品,除开在购物清单上你可能为每件物品都单独列一行,在 Python 中你需要在它们之间多加上一个逗号。 + +项目的列表应该用方括号括起来,这样 Python 才能理解到你正在指定一张列表。一旦你创建了一张列表,你可以添加、移除或搜索列表中的项目。既然我们可以添加或删除项目,我们会说列表是一种\*可变的(Mutable)\*数据类型,意即,这种类型是可以被改变的。 + +## 有关对象与类的快速介绍 + +虽然到目前为止我经常推迟有关对象(Object)与类(Class)的讨论,但现在对它们进行稍许解释能够有助于你更好地理解列表。我们将在[后面的章节](14.oop.md#oop)讨论有关它们的更多细节。 + +列表是使用对象与类的实例。当我们启用一个变量 `i` 并将整数 `5` 赋值给它时,你可以认为这是在创建一个 `int` _类_(即类型)之下的_对象_(即实例) `i`。实际上,你可以阅读 `help(int)` 来了解更多内容。 + +一个类也可以带有_方法(Method)_,也就是说对这个类定义仅对于它启用某个函数。只有当你拥有一个属于该类的对象时,你才能使用这些功能。举个例子,Python 为 `list` 类提供了一种 `append` 方法,能够允许你向列表末尾添加一个项目。例如 `mylist.append('an item')` 将会向列表 `mylist` 添加一串字符串。在这里要注意到我们通过使用点号的方法来访问对象。 + +一个类同样也可以具有_字段(Field)_,它是只为该类定义且只为该类所用的变量。只有当你拥有一个属于该类的对象时,你才能够使用这些变量或名称。字段同样可以通过点号来访问,例如 `mylist.field`。 + +案例(保存为 `ds_using_list.py`): + +```python +# This is my shopping list +shoplist = ['apple', 'mango', 'carrot', 'banana'] + +print('I have', len(shoplist), 'items to purchase.') + +print('These items are:', end=' ') +for item in shoplist: + print(item, end=' ') + +print('\nI also have to buy rice.') +shoplist.append('rice') +print('My shopping list is now', shoplist) + +print('I will sort my list now') +shoplist.sort() +print('Sorted shopping list is', shoplist) + +print('The first item I will buy is', shoplist[0]) +olditem = shoplist[0] +del shoplist[0] +print('I bought the', olditem) +print('My shopping list is now', shoplist) + +``` + +输出: + +```python +$ python ds_using_list.py +I have 4 items to purchase. +These items are: apple mango carrot banana +I also have to buy rice. +My shopping list is now ['apple', 'mango', 'carrot', 'banana', 'rice'] +I will sort my list now +Sorted shopping list is ['apple', 'banana', 'carrot', 'mango', 'rice'] +The first item I will buy is apple +I bought the apple +My shopping list is now ['banana', 'carrot', 'mango', 'rice'] + +``` + +**它是如何工作的** + +变量 `shoplist` 是一张为即将前往市场的某人准备的购物清单。在 `shoplist` 中,我们只存储了一些字符串,它们是我们需要购买的物品的名称,但是你可以向列表中添加\_任何类型的对象\_,包括数字,甚至是其它列表。 + +我们还使用 `for...in` 循环来遍历列表中的每一个项目。学习到现在,你必须有一种列表也是一个序列的意识。有关序列的特性将会在[稍后的章节](12.data\_structures.md#sequence)予以讨论。 + +在这里要注意在调用 `print` 函数时我们使用 `end` 参数,这样就能通过一个空格来结束输出工作,而不是通常的换行。 + +接下来,如我们讨论过的那般,我们通过列表对象中的 `append` 方法向列表中添加一个对象。然后,我们将列表简单地传递给 `print` 函数,整洁且完整地打印出列表内容,以此来检查项目是否被切实地添加进列表之中。 + +接着,我们列表的 `sort` 方法对列表进行排序。在这里要着重理解到这一方法影响到的是列表本身,而不会返回一个修改过的列表——这与修改字符串的方式并不相同。同时,这也是我们所说的,列表是\_可变的(Mutable)_而字符串是\_不可变的(Immutable)_。 + +随后,当我们当我们在市场上买回某件商品时,我们需要从列表中移除它。我们通过使用 `del` 语句来实现这一需求。在这里,我们将给出我们希望从列表中移除的商品,`del` 语句则会为我们从列表中移除对应的项目。我们希望移除列表中的第一个商品,因此我们使用 `del shoplist[0]`(要记住 Python 从 0 开始计数)。 + +如果你想了解列表对象定义的所有方法,可以通过 `help(list)` 来了解更多细节。 + +## 元组 + +元组(Tuple)用于将多个对象保存到一起。你可以将它们近似地看作列表,但是元组不能提供列表类能够提供给你的广泛的功能。元组的一大特征类似于字符串,它们是_不可变的_,也就是说,你不能编辑或更改元组。 + +元组是通过特别指定项目来定义的,在指定项目时,你可以给它们加上括号,并在括号内部用逗号进行分隔。 + +元组通常用于保证某一语句或某一用户定义的函数可以安全地采用一组数值,意即元组内的数值不会改变。 + +案例(保存为 `ds_using_tuple.py`): + +```python +# 我会推荐你总是使用括号 +# 来指明元组的开始与结束 +# 尽管括号是一个可选选项。 +# 明了胜过晦涩,显式优于隐式。 +zoo = ('python', 'elephant', 'penguin') +print('Number of animals in the zoo is', len(zoo)) + +new_zoo = 'monkey', 'camel', zoo +print('Number of cages in the new zoo is', len(new_zoo)) +print('All animals in new zoo are', new_zoo) +print('Animals brought from old zoo are', new_zoo[2]) +print('Last animal brought from old zoo is', new_zoo[2][2]) +print('Number of animals in the new zoo is', + len(new_zoo)-1+len(new_zoo[2])) + +``` + +输出: + +```python +$ python ds_using_tuple.py +Number of animals in the zoo is 3 +Number of cages in the new zoo is 3 +All animals in new zoo are ('monkey', 'camel', ('python', 'elephant', 'penguin')) +Animals brought from old zoo are ('python', 'elephant', 'penguin') +Last animal brought from old zoo is penguin +Number of animals in the new zoo is 5 + +``` + +**它是如何工作的** + +变量 `zoo` 指的是一个包含项目的元组。我们能够看到 `len` 函数在此处用来获取元组的长度。这也表明元组同时也是一个[序列](12.data\_structures.md#sequence)。 + +现在,我们将这些动物从即将关闭的老动物园(Zoo)转移到新的动物园中。因此,`new_zoo` 这一元组包含了一些本已存在的动物以及从老动物园转移过去的动物。让我们回到话题中来,在这里要注意到元组中所包含的元组不会失去其所拥有的身份。 + +如同我们在列表里所做的那般,我们可以通过在方括号中指定项目所处的位置来访问元组中的各个项目。这种使用方括号的形式被称作\_索引(Indexing)\_运算符。我们通过指定 `new_zoo[2]` 来指定 `new_zoo` 中的第三个项目,我们也可以通过指定 `new_zoo[2][2]` 来指定 `new_zoo` 元组中的第三个项目中的第三个项目。一旦你习惯了这种语法你就会觉得这其实非常简单。 + +> **包含 0 或 1 个项目的元组** +> +> 一个空的元组由一对圆括号构成,就像 `myempty = ()` 这样。然而,一个只拥有一个项目的元组并不像这样简单。你必须在第一个(也是唯一一个)项目的后面加上一个逗号来指定它,如此一来 Python 才可以识别出在这个表达式想表达的究竟是一个元组还是只是一个被括号所环绕的对象,也就是说,如果你想指定一个包含项目 `2` 的元组,你必须指定 `singleton = (2, )`。 + +> **针对 Perl 程序员的提示** +> +> 列表中的列表不会丢失其标识,即列表不会像在 Perl 里那般会被打散(Flattened)。这同样也适用于元组中的元组、列表中的元组或元组中的列表等等情况。对于 Python 而言,它们只是用一个对象来存储另一个对象,不过仅此而已。 + +## 字典 + +字典就像一本地址簿,如果你知道了他或她的姓名,你就可以在这里找到其地址或是能够联系上对方的更多详细信息,换言之,我们将_键值(Keys)_(即姓名)与_值(Values)_(即地址等详细信息)联立到一起。在这里要注意到键值必须是唯一的,正如在现实中面对两个完全同名的人你没办法找出有关他们的正确信息。 + +另外要注意的是你只能使用不可变的对象(如字符串)作为字典的键值,但是你可以使用可变或不可变的对象作为字典中的值。基本上这段话也可以翻译为你只能使用简单对象作为键值。 + +在字典中,你可以通过使用符号构成 `d = {key : value1 , key2 : value2}` 这样的形式,来成对地指定键值与值。在这里要注意到成对的键值与值之间使用冒号分隔,而每一对键值与值则使用逗号进行区分,它们全都由一对花括号括起。 + +另外需要记住,字典中的成对的键值—值配对不会以任何方式进行排序。如果你希望为它们安排一个特别的次序,只能在使用它们之前自行进行排序。 + +你将要使用的字典是属于 `dict` 类下的实例或对象。 + +案例(保存为 `ds_using_dict.py`): + +```python +# “ab”是地址(Address)簿(Book)的缩写 + +ab = { + 'Swaroop': 'swaroop@swaroopch.com', + 'Larry': 'larry@wall.org', + 'Matsumoto': 'matz@ruby-lang.org', + 'Spammer': 'spammer@hotmail.com' +} + +print("Swaroop's address is", ab['Swaroop']) + +# 删除一对键值—值配对 +del ab['Spammer'] + +print('\nThere are {} contacts in the address-book\n'.format(len(ab))) + +for name, address in ab.items(): + print('Contact {} at {}'.format(name, address)) + +# 添加一对键值—值配对 +ab['Guido'] = 'guido@python.org' + +if 'Guido' in ab: + print("\nGuido's address is", ab['Guido']) + +``` + +输出: + +```python +$ python ds_using_dict.py +Swaroop's address is swaroop@swaroopch.com + +There are 3 contacts in the address-book + +Contact Swaroop at swaroop@swaroopch.com +Contact Matsumoto at matz@ruby-lang.org +Contact Larry at larry@wall.org + +Guido's address is guido@python.org + +``` + +**它是如何工作的** + +我们通过已经讨论过的符号体系来创建字典 `ab`。然后我们通过使用索引运算符来指定某一键值以访问相应的键值—值配对,有关索引运算符的方法我们已经在列表与元组部分讨论过了。你可以观察到这之中的语法非常简单。 + +我们可以通过我们的老朋友——`del` 语句——来删除某一键值—值配对。我们只需指定字典、包含需要删除的键值名称的索引算符,并将其传递给 `del` 语句。这一操作不需要你知道与该键值相对应的值。 + +接着,我们通过使用字典的 `items` 方法来访问字典中的每一对键值—值配对信息,这一操作将返回一份包含元组的列表,每一元组中则包含了每一对相应的信息——键值以及其相应的值。我们检索这一配对,并通过 `for...in` 循环将每一对配对的信息相应地分配给 `name` 与 `address` 变量,并将结果打印在 `for` 代码块中。 + +如果想增加一堆新的键值—值配对,我们可以简单地通过使用索引运算符访问一个键值并为其分配与之相应的值,就像我们在上面的例子中对 Guido 键值所做的那样。 + +我们可以使用 `in` 运算符来检查某对键值—值配对是否存在。 + +要想了解有关 `dict` 类的更多方法,请参阅 `help(dict)`。 + +> **关键字参数与字典** +> +> 如果你曾在你的函数中使用过关键词参数,那么你就已经使用过字典了!你只要这么想——你在定义函数时的参数列表时,就指定了相关的键值—值配对。当你在你的函数中访问某一变量时,它其实就是在访问字典中的某个键值。(在编译器设计的术语中,这叫作\_符号表(Symbol Table)\_) + +## 序列 + +列表、元组和字符串可以看作序列(Sequence)的某种表现形式,可是究竟什么是序列,它又有什么特别之处? + +序列的主要功能是_资格测试(Membership Test)_(也就是 `in` 与 `not in` 表达式)和_索引操作(Indexing Operations)_,它们能够允许我们直接获取序列中的特定项目。 + +上面所提到的序列的三种形态——列表、元组与字符串,同样拥有一种\*切片(Slicing)\*运算符,它能够允许我们序列中的某段切片——也就是序列之中的一部分。 + +案例(保存为 `ds_seq.py`): + +```python +shoplist = ['apple', 'mango', 'carrot', 'banana'] +name = 'swaroop' + +# Indexing or 'Subscription' operation # +# 索引或“下标(Subscription)”操作符 # +print('Item 0 is', shoplist[0]) +print('Item 1 is', shoplist[1]) +print('Item 2 is', shoplist[2]) +print('Item 3 is', shoplist[3]) +print('Item -1 is', shoplist[-1]) +print('Item -2 is', shoplist[-2]) +print('Character 0 is', name[0]) + +# Slicing on a list # +print('Item 1 to 3 is', shoplist[1:3]) +print('Item 2 to end is', shoplist[2:]) +print('Item 1 to -1 is', shoplist[1:-1]) +print('Item start to end is', shoplist[:]) + +# 从某一字符串中切片 # +print('characters 1 to 3 is', name[1:3]) +print('characters 2 to end is', name[2:]) +print('characters 1 to -1 is', name[1:-1]) +print('characters start to end is', name[:]) + +``` + +输出: + +``` +$ python ds_seq.py +Item 0 is apple +Item 1 is mango +Item 2 is carrot +Item 3 is banana +Item -1 is banana +Item -2 is carrot +Character 0 is s +Item 1 to 3 is ['mango', 'carrot'] +Item 2 to end is ['carrot', 'banana'] +Item 1 to -1 is ['mango', 'carrot'] +Item start to end is ['apple', 'mango', 'carrot', 'banana'] +characters 1 to 3 is wa +characters 2 to end is aroop +characters 1 to -1 is waroo +characters start to end is swaroop + +``` + +**它是如何工作的** + +首先,我们已经了解了如何通过使用索引来获取序列中的各个项目。这也被称作\_下标操作(Subscription Operation)\_。如上所示,每当你在方括号中为序列指定一个数字,Python 将获取序列中与该位置编号相对应的项目。要记得 Python 从 0 开始计数。因此 `shoplist[0]` 将获得 `shoplist` 序列中的第一个项目,而 `shoplist[3]` 将获得第四个项目。 + +索引操作也可以使用负数,在这种情况下,位置计数将从队列的末尾开始。因此,`shoplist[-1]` 指的是序列的最后一个项目,`shoplist[-2]` 将获取序列中倒数第二个项目。 + +你需要通过指定序列名称来进行序列操作,在指定时序列名称后面可以跟一对数字——这是可选的操作,这一对数字使用方括号括起,并使用冒号分隔。在这里需要注意,它与你至今为止使用的索引操作显得十分相像。但是你要记住数字是可选的,冒号却不是。 + +在切片操作中,第一个数字(冒号前面的那位)指的是切片开始的位置,第二个数字(冒号后面的那位)指的是切片结束的位置。如果第一位数字没有指定,Python 将会从序列的起始处开始操作。如果第二个数字留空,Python 将会在序列的末尾结束操作。要注意的是切片操作会在开始处返回 _start_,并在 _end_ 前面的位置结束工作。也就是说,序列切片将包括起始位置,但不包括结束位置。 + +因此,`shoplist[1:3]` 返回的序列的一组切片将从位置 1 开始,包含位置 2 并在位置 3 时结束,因此,这块_切片_返回的是两个项目。类似地,`shoplist[:]` 返回的是整个序列。 + +你同样可以在切片操作中使用负数位置。使用负数时位置将从序列末端开始计算。例如,`shoplist[:-1]` 强返回一组序列切片,其中不包括序列的最后一项项目,但其它所有项目都包含其中。 + +你同样可以在切片操作中提供第三个参数,这一参数将被视为切片的\_步长(Step)\_(在默认情况下,步长大小为 1): + +```python +>>> shoplist = ['apple', 'mango', 'carrot', 'banana'] +>>> shoplist[::1] +['apple', 'mango', 'carrot', 'banana'] +>>> shoplist[::2] +['apple', 'carrot'] +>>> shoplist[::3] +['apple', 'banana'] +>>> shoplist[::-1] +['banana', 'carrot', 'mango', 'apple'] +``` + +你会注意到当步长为 2 时,我们得到的是第 0、2、4…… 位项目。当步长为 3 时,我们得到的是第 0、3……位项目。 + +你可以在 Python 解释器中交互地尝试不同的切片方式的组合,这将帮助你立即看到结果。序列的一大优点在于你可以使用同样的方式访问元组、列表与字符串。 + +## 集合 + +集合(Set)是简单对象的\_无序\_集合(Collection)。当集合中的项目存在与否比起次序或其出现次数更加重要时,我们就会使用集合。 + +通过使用集合,你可以测试某些对象的资格或情况,检查它们是否是其它集合的子集,找到两个集合的交集,等等。 + +```python +>>> bri = set(['brazil', 'russia', 'india']) +>>> 'india' in bri +True +>>> 'usa' in bri +False +>>> bric = bri.copy() +>>> bric.add('china') +>>> bric.issuperset(bri) +True +>>> bri.remove('russia') +>>> bri & bric # OR bri.intersection(bric) +{'brazil', 'india'} +``` + +**它是如何工作的** + +这个案例几乎不言自明,因为它涉及的是学校所教授的数学里的基础集合知识。 + +## 引用 + +当你创建了一个对象并将其分配给某个变量时,变量只会\_查阅(Refer)\_某个对象,并且它也不会代表对象本身。也就是说,变量名只是指向你计算机内存中存储了相应对象的那一部分。这叫作将名称\*绑定(Binding)\*给那一个对象。 + +一般来说,你不需要去关心这个,不过由于这一引用操作困难会产生某些微妙的效果,这是需要你注意的: + +案例(保存为 `ds_reference.py`): + +```python +print('Simple Assignment') +shoplist = ['apple', 'mango', 'carrot', 'banana'] +# mylist 只是指向同一对象的另一种名称 +mylist = shoplist + +# 我购买了第一项项目,所以我将其从列表中删除 +del shoplist[0] + +print('shoplist is', shoplist) +print('mylist is', mylist) +# 注意到 shoplist 和 mylist 二者都 +# 打印出了其中都没有 apple 的同样的列表,以此我们确认 +# 它们指向的是同一个对象 + +print('Copy by making a full slice') +# 通过生成一份完整的切片制作一份列表的副本 +mylist = shoplist[:] +# 删除第一个项目 +del mylist[0] + +print('shoplist is', shoplist) +print('mylist is', mylist) +# 注意到现在两份列表已出现不同 + +``` + +输出: + +```python +$ python ds_reference.py +Simple Assignment +shoplist is ['mango', 'carrot', 'banana'] +mylist is ['mango', 'carrot', 'banana'] +Copy by making a full slice +shoplist is ['mango', 'carrot', 'banana'] +mylist is ['carrot', 'banana'] + +``` + +**它是如何工作的** + +大部分解释已经在注释中提供。 + +你要记住如果你希望创建一份诸如序列等复杂对象的副本(而非整数这种简单的\_对象(Object)\_),你必须使用切片操作来制作副本。如果你仅仅是将一个变量名赋予给另一个名称,那么它们都将“查阅”同一个对象,如果你对此不够小心,那么它将造成麻烦。 + +> **针对 Perl 程序员的提示** +> +> 要记住列表的赋值语句**不会**创建一份副本。你必须使用切片操作来生成一份序列的副本。 + +## 有关字符串的更多内容 + +在早些时候我们已经详细讨论过了字符串。还有什么可以知道的吗?还真有,想必你还不知道字符串同样也是一种对象,并且它也具有自己的方法,可以做到检查字符串中的一部分或是去掉空格等几乎一切事情! + +你在程序中使用的所有字符串都是 `str` 类下的对象。下面的案例将演示这种类之下一些有用的方法。要想获得这些方法的完成清单,你可以查阅 `help(str)`。 + +案例(保存为 `ds_str_methods.py`): + +```python +# 这是一个字符串对象 +name = 'Swaroop' + +if name.startswith('Swa'): + print('Yes, the string starts with "Swa"') + +if 'a' in name: + print('Yes, it contains the string "a"') + +if name.find('war') != -1: + print('Yes, it contains the string "war"') + +delimiter = '_*_' +mylist = ['Brazil', 'Russia', 'India', 'China'] +print(delimiter.join(mylist)) + +``` + +输出: + +```python +$ python ds_str_methods.py +Yes, the string starts with "Swa" +Yes, it contains the string "a" +Yes, it contains the string "war" +Brazil_*_Russia_*_India_*_China + +``` + +**它是如何工作的** + +在这里,我们会看见一此操作中包含了好多字符串方法。`startswith` 方法用于查找字符串是否以给定的字符串内容开头。`in` 运算符用以检查给定的字符串是否是查询的字符串中的一部分。 + +`find` 方法用于定位字符串中给定的子字符串的位置。如果找不到相应的子字符串,`find` 会返回 -1。`str` 类同样还拥有一个简洁的方法用以 `联结(Join)`序列中的项目,其中字符串将会作为每一项目之间的分隔符,并以此生成并返回一串更大的字符串。 + +## 总结 + +我们已经详细探讨了 Python 中内置的多种不同的数据结构。这些数据结构对于编写大小适中的 Python 程序而言至关重要。 + +现在我们已经具备了诸多有关 Python 的基本知识,接下来我们将会了解如何设计并编写一款真实的 Python 程序。 + +*** + +1. 原文作“Reference”,沈洁元译本译作“参考”。此处译名尚存疑,如有更好的翻译建议还请指出。 diff --git a/13.problem_solving.md b/13.problem_solving.md new file mode 100644 index 00000000..9d7c248d --- /dev/null +++ b/13.problem_solving.md @@ -0,0 +1,416 @@ +# 解决问题 + +我们已经探索了 Python 语言中的许多部分,现在我们将通过设计并编写一款程序来了解如何把这些部分组合到一起。这些程序一定是能\_做到\_一些有用的事情。这其中的方法就是去学习如何靠你自己来编写一份 Python 脚本。 + +## 问题 + +我们希望解决的问题如下: + +> 我想要一款程序来备份我所有的重要文件。 + +虽然这是一个简单的问题,但是其中并没有足够的信息有助于让我们开始规划一份解决方案。我们需要进行一些_分析(Analysis)_。例如,我们应该如何指定\_哪些\_文件是我们需要备份的?它们应该\_如何\_进行备份?储存到\_哪里\_? + +在正确地分析了这些问题过后,我们便开始\*设计(Design)\*我们的程序。我们将列出一份关于我们的程序应如何运转的清单。在这个案例中,我已经编写了如下清单来说明\_我\_将如何工作。如果由你来设计程序,你可能不会做出同样的分析,因为每个人都有其自己的行事方式,所以出现不同是完全正常、且正确的。 + +* 需要备份的文件与目录应在一份列表中予以指定。 +* 备份必须存储在一个主备份目录中。 +* 备份文件将打包压缩成 zip 文件。 +* zip 压缩文件的文件名由当前日期与时间构成。 +* 我们使用在任何 GNU/Linux 或 Unix 发行版中都会默认提供的标准 `zip` 命令进行打包。在这里你需要了解到只要有命令行界面,你就可以使用任何需要用到的压缩或归档命令。 + +> **针对 Windows 用户的提示** +> +> Windows 用户可以从 [GnuWin32 项目页面](http://gnuwin32.sourceforge.net/packages/zip.htm) 上下载并[安装](http://gnuwin32.sourceforge.net/downlinks/zip.php) `zip` 命令,并将 `C:\Program Files\GnuWin32\bin` 添加至你的系统的 `PATH` 环境变量中,这一操作过程与[我们为使系统识别 Python 命令本身所做的事情](installation.md#dos-prompt)相同。 + +## 解决方案 + +由于我们的程序设计方案现在已经相当稳定,我们便可以开始编写代码,这个过程我们称之为\*实现(Implementation)\*我们的解决方案。 + +将下述代码保存为 `backup_ver1.py`: + +```python +import os +import time + +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: +# source = ['"C:\\My Documents"', 'C:\\Code'] +# 又例如在 Mac OS X 与 Linux 下: +source = ['/Users/swa/notes'] +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 + +#2. 备份文件必须存储在一个 +#主备份目录中 +#例如在 Windows 下: +# target_dir = 'E:\\Backup' +# 又例如在 Mac OS X 和 Linux 下: +target_dir = '/Users/swa/backup' +# 要记得将这里的目录地址修改至你将使用的路径 + +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. zip 压缩文件的文件名由当前日期与时间构成。 +target = target_dir + os.sep + \ + time.strftime('%Y%m%d%H%M%S') + '.zip' + +# 如果目标目录还不存在,则进行创建 +if not os.path.exists(target_dir): + os.mkdir(target_dir) # 创建目录 + +# 5. 我们使用 zip 命令将文件打包成 zip 格式 +zip_command = 'zip -r {0} {1}'.format(target, + ' '.join(source)) + +# 运行备份 +print('Zip command is:') +print(zip_command) +print('Running:') +if os.system(zip_command) == 0: + print('Successful backup to', target) +else: + print('Backup FAILED') + +``` + +输出: + +``` +$ python backup_ver1.py +Zip command is: +zip -r /Users/swa/backup/20140328084844.zip /Users/swa/notes +Running: + adding: Users/swa/notes/ (stored 0%) + adding: Users/swa/notes/blah1.txt (stored 0%) + adding: Users/swa/notes/blah2.txt (stored 0%) + adding: Users/swa/notes/blah3.txt (stored 0%) +Successful backup to /Users/swa/backup/20140328084844.zip + +``` + +现在,我们正处于_测试(Testing)_阶段,在这一阶段我们测试我们的程序是否能正常工作。如果其行为不符合我们的预期,那么我们需要对我们的程序进行 _Debug_ 工作,也就是说,移除程序中的 _Bug_(错误)。 + +如果上面的程序不能够正常工作,复制打印在 `Zip command is` 后面的命令,将其粘贴至 shell(在 GNU/Linux 与 Mac OS X 环境中)或 `cmd`(对于 Windows 环境),看看存在什么错误并尝试将其修复。同时你还需要检查 zip 命令手册来看看是不是哪里存在错误。如果这条命令成功运行,那么可能是错误可能存在在 Python 程序本身之中,因此你需要检查你的程序是否如上面所展示那番。 + +**它是如何工作的** + +你会注意到我们是如何一步步将我们的_设计_转化为_代码_的。 + +我们首先导入 `os` 与 `time` 模块以准备使用它们。然后,我们在 `source` 列表中指定我们需要备份的文件与目录。我们需要存储我们所有备份文件的目标目录在 `target_dir` 变量中予以指定。我们将要创建的 zip 归档文件的名字由当前日期与时间构成,在这里通过 `time.strftime()` 函数来创建。文件名将以 `.zip` 作为扩展名,并存储在 `target_dir` 目录中。 + +在这里要注意 `os.sep` 变量的使用方式——它将根据你的操作系统给出相应的分隔符,在 GNU/Linux 与 Unix 中它会是 `'/'`,在 Windows 中它会是 `'\\'`,在 Mac OS 中它会是 `':'`。使用 `os.sep` 而非直接使用这些字符有助于使我们的程序变得可移植,从而可以在上述这些系统中都能正常工作。 + +`time.strftime()` 函数会遵循某些格式(Specification),其中一种就如我们在上方程序中所使用的那样。`%Y` 将被替换成带有具体世纪的年份。`%m` 将会被替换成以 `01` 至 `12` 的十进制数所表示的月份。有关这些格式的全部列表可以在[ Python 参考手册](http://docs.python.org/3/library/time.html#time.strftime)中查询到。 + +我们使用\_连接(Concatenates)\_字符串的加法(`+`)运算符来创建目标 zip 文件的文件名,也就是说,它将两个字符串连接到一起并返回一个新的字符串。然后,我们创建了一串字符串 `zip_command`,其中包括了我们要执行的命令。如果这条命令不能正常工作,你可以把它拷贝到 Shell(GNU/Linux 终端或 DOS 提示符)中进行检查。 + +我们使用的 `zip` 命令会有一些选项与参数需要传递。`-r` 选项用以指定 zip 命令应该**递归地**(**R**ecursively)对目录进行工作,也就是说它应该包括所有的子文件夹与其中的文件。这两个选项结合到一起并可以指定一个快捷方式作 `-qr`。选项后面跟着的是将要创建的 zip 文件的名称,再往后是需要备份的文件与目录的列表。我们通过使用已经讨论过并已了解该如何运用的的字符串方法 `join` 来将列表 `source` 转换成字符串。 + +随后,我们终于可以_运行_这一使用了 `os.system` 函数的命令,这一函数可以使命令像是从_系统_中运行的。也就是说,从 shell 中运行的——如果运行成功,它将返回 `0`,如果运行失败,将返回一个错误代码。 + +根据命令运行的结果是成功还是失败,我们将打印出与之相应的信息来告诉你备份的结果究竟如何。 + +就是这样,我们便创建了一份用以备份我们的重要文件的脚本! + +> **针对 Windows 用户的提示** +> +> 除了使用双反斜杠转义序列,你还可以使用原始字符串。例如使用 `'C:\\Documents'` 或 `r'C:\Documents'`。然而,_不_要使用 `'C:\Documents'`,因为它将被识别为你使用了一个未知的转义序列 `\D` 来结束路径的输入。 + +现在,我们已经拥有了一份可以正常工作的备份脚本,我们可以在任何我们需要备份文件的时候使用它。这被称作软件的\*操作(Operation)_或_部署(Deployment)\*阶段。 + +上面所展示的程序能够正常工作,但是(通常)第一个程序都不会按照你所期望的进行工作。可能是因为你没有正确地设计程序,或如果你在输入代码时出现了错误。出现这些情况时,在恰当的时候,你需要回到设计阶段,或者你需要对你的程序进行 Debug 工作。 + +## 第二版 + +我们的第一版脚本已经能够工作了。然而,我们还可以对它作出一些改进,从而使它能够更好地在每一天都可以正常工作。我们将这一阶段称之为软件的\*维护(Maintenance)\*阶段。 + +我认为有一种颇为有用的改进是起用一种更好的文件命名机制——使用\_时间\_作为文件名,存储在以当前\_日期\_为名字的文件夹中,这一文件夹则照常存储在主备份目录下。这种机制的第一个有点在于你的备份会以分层的形式予以存储,从而使得它们能更易于管理。第二个优点是文件名能够更短。第三个优点在于由于只有当天进行了备份才会创建相应的目录,独立的目录能够帮助你快速地检查每天是否都进行了备份。 + +保存为 `backup_ver2.py`: + +```python +import os +import time + +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: +# source = ['"C:\\My Documents"', 'C:\\Code'] +# 又例如在 Mac OS X 与 Linux 下: +source = ['/Users/swa/notes'] +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 + +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: +# target_dir = 'E:\\Backup' +# 又例如在 Mac OS X 和 Linux 下: +target_dir = '/Users/swa/backup' +# 要记得将这里的目录地址修改至你将使用的路径 + +# 如果目标目录不存在则创建目录 +if not os.path.exists(target_dir): + os.mkdir(target_dir) # 创建目录 + +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的子目录名称 +today = target_dir + os.sep + time.strftime('%Y%m%d') +# 将当前时间作为 zip 文件的文件名 +now = time.strftime('%H%M%S') + +# zip 文件名称格式 +target = today + os.sep + now + '.zip' + +# 如果子目录尚不存在则创建一个 +if not os.path.exists(today): + os.mkdir(today) + print('Successfully created directory', today) + +# 5. 我们使用 zip 命令将文件打包成 zip 格式 +zip_command = 'zip -r {0} {1}'.format(target, + ' '.join(source)) + +# 运行备份 +print('Zip command is:') +print(zip_command) +print('Running:') +if os.system(zip_command) == 0: + print('Successful backup to', target) +else: + print('Backup FAILED') + +``` + +输出: + +```python +$ python backup_ver2.py +Successfully created directory /Users/swa/backup/20140329 +Zip command is: +zip -r /Users/swa/backup/20140329/073201.zip /Users/swa/notes +Running: + adding: Users/swa/notes/ (stored 0%) + adding: Users/swa/notes/blah1.txt (stored 0%) + adding: Users/swa/notes/blah2.txt (stored 0%) + adding: Users/swa/notes/blah3.txt (stored 0%) +Successful backup to /Users/swa/backup/20140329/073201.zip +``` + +**它是如何工作的** + +程序的大部分都保持不变。有所改变的部分是我们通过 `os.path.exists` 函数来检查主文件目录中是否已经存在了以当前日期作为名称的子目录。如果尚未存在,我们通过 `os.mkdir` 函数来创建一个。 + +## 第三版 + +第二版在我要制作多份备份时能够正常工作,但当备份数量过于庞大时,我便很难找出备份之间有什么区别了。例如,我可能对我的程序或者演示文稿做了重大修改,然后我想将这些修改与 zip 文件的文件名产生关联。这可以通过将用户提供的注释内容添加到文件名中来实现。 + +预先提醒:下面给出的程序将不会正常工作,所以不必惊慌,只需跟着案例去做因为你要在里面学上一课。 + +保存为 `backup_ver3.py`: + +```python +import os +import time + +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: +# source = ['"C:\\My Documents"', 'C:\\Code'] +# 又例如在 Mac OS X 与 Linux 下: +source = ['/Users/swa/notes'] +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 + +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: +# target_dir = 'E:\\Backup' +# 又例如在 Mac OS X 和 Linux 下: +target_dir = '/Users/swa/backup' +# 要记得将这里的目录地址修改至你将使用的路径 + +# 如果目标目录还不存在,则进行创建 +if not os.path.exists(target_dir): + os.mkdir(target_dir) # 创建目录 + +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的 +# 子目录名称 +today = target_dir + os.sep + time.strftime('%Y%m%d') +# 将当前时间作为 zip 文件的文件名 +now = time.strftime('%H%M%S') + +# 添加一条来自用户的注释以创建 +# zip 文件的文件名 +comment = input('Enter a comment --> ') +# 检查是否有评论键入 +if len(comment) == 0: + target = today + os.sep + now + '.zip' +else: + target = today + os.sep + now + '_' + + comment.replace(' ', '_') + '.zip' + +# 如果子目录尚不存在则创建一个 +if not os.path.exists(today): + os.mkdir(today) + print('Successfully created directory', today) + +# 5. 我们使用 zip 命令将文件打包成 zip 格式 +zip_command = "zip -r {0} {1}".format(target, + ' '.join(source)) + +# 运行备份 +print('Zip command is:') +print(zip_command) +print('Running:') +if os.system(zip_command) == 0: + print('Successful backup to', target) +else: + print('Backup FAILED') + +``` + +输出: + +``` +$ python backup_ver3.py + File "backup_ver3.py", line 39 + target = today + os.sep + now + '_' + + ^ +SyntaxError: invalid syntax + +``` + +**它是如何(不)工作的** + +_**这个程序它跑不起来!**_Python 会说程序之中存在着语法错误,这意味着脚本并未拥有 Python 期望看见的结构。当我们观察 Python 给出的错误时,会看见它同时也告诉我们它检测到错误的额地方。所以我们开始从那个地方开始对我们的程序进行 _Debug_ 工作。 + +仔细观察,我们会发现有一独立的逻辑行被分成了两行物理行,但我们并未指定这两行物理行应该是一起的。基本上,Python 已经发现了该逻辑行中的加法运算符(`+`)没有任何操作数,因此它不知道接下来应当如何继续。因此,我们在程序中作出修正。当我们发现程序中的错误并对其进行修正时,我们称为**“错误修复(Bug Fixing)”**。 + +## 第四版 + +保存为 `backup_ver4.py`: + +```python +import os +import time + +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: +# source = ['"C:\\My Documents"', 'C:\\Code'] +# 又例如在 Mac OS X 与 Linux 下: +source = ['/Users/swa/notes'] +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 + +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: +# target_dir = 'E:\\Backup' +# 又例如在 Mac OS X 和 Linux 下: +target_dir = '/Users/swa/backup' +# 要记得将这里的目录地址修改至你将使用的路径 + +# 如果目标目录还不存在,则进行创建 +if not os.path.exists(target_dir): + os.mkdir(target_dir) # 创建目录 + +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的 +# 子目录名称 +today = target_dir + os.sep + time.strftime('%Y%m%d') +# 将当前时间作为 zip 文件的文件名 +now = time.strftime('%H%M%S') + +# 添加一条来自用户的注释以创建 +# zip 文件的文件名 +comment = input('Enter a comment --> ') +# 检查是否有评论键入 +if len(comment) == 0: + target = today + os.sep + now + '.zip' +else: + target = today + os.sep + now + '_' + \ + comment.replace(' ', '_') + '.zip' + +# 如果子目录尚不存在则创建一个 +if not os.path.exists(today): + os.mkdir(today) + print('Successfully created directory', today) + +# 5. 我们使用 zip 命令将文件打包成 zip 格式 +zip_command = 'zip -r {0} {1}'.format(target, + ' '.join(source)) + +# 运行备份 +print('Zip command is:') +print(zip_command) +print('Running:') +if os.system(zip_command) == 0: + print('Successful backup to', target) +else: + print('Backup FAILED') + +``` + +输出: + +```python +$ python backup_ver4.py +Enter a comment --> added new examples +Zip command is: +zip -r /Users/swa/backup/20140329/074122_added_new_examples.zip /Users/swa/notes +Running: + adding: Users/swa/notes/ (stored 0%) + adding: Users/swa/notes/blah1.txt (stored 0%) + adding: Users/swa/notes/blah2.txt (stored 0%) + adding: Users/swa/notes/blah3.txt (stored 0%) +Successful backup to /Users/swa/backup/20140329/074122_added_new_examples.zip + +``` + +**它是如何工作的** + +现在程序可以正常工作了!让我们来回顾一下我们在第三版中所作出的实际的增强工作。我们使用 `input` 函数来接受用户的注释内容,并通过 `len` 函数来检查输入内容的长度,以检查用户是否确实输入了什么内容。如果用户未输入任何内容而直接敲下了 `enter` 键(也许这份备份只是一份例行备份而没作出什么特殊的修改),那么我们将继续我们以前所做的工作。 + +不过,如果用户输入了某些注释内容,那么它将会被附加进 zip 文件的文件名之中,处在 `.zip` 扩展名之前。在这里需要注意的是我们用下划线替换注释中的空格——这是因为管理没有空格的文件名总会容易得多。 + +## 继续改进 + +第四版程序已经是一份对大多数用户来说都能令人满意地工作运行的脚本了,不过总会有改进的余地在。例如,你可以在程序中添加 `-v` 选项来指定程序的显示信息的\_详尽\_[^1]程度,从而使你的程序可以更具说服力,或者是添加 `-q` 选项使程序能\_静默(Quiet)\_运行。 + +另一个可以增强的方向是在命令行中允许额外的文件与目录传递到脚本中。我们可以从 `sys.argv` 列表中获得这些名称,然后我们可以通过`list` 类提供的 `extend` 方法把它们添加到我们的 `source` 列表中. + +最重要的改进方向是不使用 `os.system` 方法来创建归档文件,而是使用 [zipfile](http://docs.python.org/3/library/zipfile.html) 或 [tarfile](http://docs.python.org/3/library/tarfile.html) 内置的模块来创建它们的归档文件。这些都是标准库的一部分,随时供你在你的电脑上没有 zip 程序作为没有外部依赖的情况下使用这些功能。 + +不过,在上面的例子中,我一直都在使用 `os.system` 这种方式作为创建备份的手段,这样就能保证案例对于所有人来说都足够简单同时也确实有用。 + +你可以试试编写第五版脚本吗?在脚本中使用 [zipfile](http://docs.python.org/3/library/zipfile.html) 模块而非 `os.system` 调用。 + +## 软件开发流程 + +我们已经经历了开发一款软件的流程中的各个`阶段(Phases)`。现在可以将这些阶段总结如下: + +1. What/做什么(分析) +2. How/怎么做(设计) +3. Do It/开始做(执行) +4. Test/测试(测试与修复错误) +5. Use/使用(操作或开发) +6. Maintain/维护(改进) + +编写程序时推荐的一种方式是遵循我们在编写备份脚本时所经历的步骤:进行分析与设计;开始实现一个简单版本;测试并修复错误;开始使用以确保工作状况皆如期望那般。现在,你可以添加任何你所希望拥有的功能,并继续去重复这一“开始做—测试—使用”循环,需要做多少次就去做多少次。 + +要记住: + +> 程序是成长起来的,不是搭建出来的。 (Software is grown, not built.) ——[Bill de hÓra](http://97things.oreilly.com/wiki/index.php/Great\_software\_is\_not\_built,\_it\_is\_grown) + +## 总结 + +我们已经看到了如何创建我们自己的 Python 程序与脚本,也了解了编写这些程序需要经历的数个阶段。或许你会发现我们在本章中学习的内容对于编写你自己的程序很有帮助,这样你就能慢慢习惯 Python,同样包括它解决问题的方式。 + +接下来,我们将讨论面向对象编程。 + +*** + +[^1]: 原文作 Verbosity,沈洁元译本译作“交互”。 diff --git a/14.oop.md b/14.oop.md new file mode 100644 index 00000000..c04db0c9 --- /dev/null +++ b/14.oop.md @@ -0,0 +1,364 @@ +# 面向对象编程 + +在至今我们编写的所有程序中,我们曾围绕函数设计我们的程序,也就是那些能够处理数据的代码块。这被称作\_面向过程(Procedure-oriented)\_的编程方式。还有另外一种组织起你的程序的方式,它将数据与功能进行组合,并将其包装在被称作“对象”的东西内。在大多数情况下,你可以使用过程式编程,但是当你需要编写一个大型程序或面对某一更适合此方法的问题时,你可以考虑使用面向对象式的编程技术。 + +类与对象是面向对象编程的两个主要方面。一个**类(Class)能够创建一种新的\_类型(Type)\_,其中对象(Object)就是类的实例(Instance)**。可以这样来类比:你可以拥有类型 `int` 的变量,也就是说存储整数的变量是 `int` 类的实例(对象)。 + +> **针对静态编程语言程序员的提示** +> +> 请注意,即使是整数也会被视为对象(`int` 类的对象)。这不同于 C++ 与 Java(1.5 版之前),在它们那儿整数是原始内置类型。 +> +> 有关类的更多详细信息,请参阅 `help(int)`。 +> +> C# 与 Java 1.5 程序员会发现这与_装箱与拆箱(Boxing and Unboxing)_概念颇有相似之处。 + +对象可以使用\_属于\_它的普通变量来存储数据。这种从属于对象或类的变量叫作**字段(Field)**。对象还可以使用\_属于\_类的函数来实现某些功能,这种函数叫作类的**方法(Method)**。这两个术语很重要,它有助于我们区分函数与变量,哪些是独立的,哪些又是属于类或对象的。总之,字段与方法通称类的**属性(Attribute)**。 + +字段有两种类型——它们属于某一类的各个实例或对象,或是从属于某一类本身。它们被分别称作**实例变量(Instance Variables)与类变量(Class Variables)**。 + +通过 `class` 关键字可以创建一个类。这个类的字段与方法可以在缩进代码块中予以列出。 + +## `self` + +类方法与普通函数只有一种特定的区别——前者必须多加一个参数在参数列表开头,这个名字必须添加到参数列表的开头,但是你_不用_在你调用这个功能时为这个参数赋值,Python 会为它提供。这种特定的变量引用的是对象\_本身\_,按照惯例,它被赋予 `self` 这一名称。 + +尽管你可以为这一参数赋予任何名称,但是\_强烈推荐\_你使用 `self` 这一名称——其它的任何一种名称绝对会引人皱眉。使用一个标准名称能带来诸多好处——任何一位你的程序的读者能够立即认出它,甚至是专门的 IDE(Integrated Development Environments,集成开发环境)也可以为你提供帮助,只要你使用了 `self` 这一名称。 + +> **针对 C++/Java/C# 程序员的提示** +> +> Python 中的 `self` 相当于 C++ 中的 `this` 指针以及 Java 与 C# 中的 `this` 引用。 + +你一定会在想 Python 是如何给 `self` 赋值的,以及为什么你不必给它一个值。一个例子或许会让这些疑问得到解答。假设你有一个 `MyClass` 的类,这个类下有一个实例 `myobject`。当你调用一个这个对象的方法,如 `myobject.method(arg1, arg2)` 时,Python 将会自动将其转换成 `MyClass.method(myobject, arg1, arg2)`——这就是 `self` 的全部特殊之处所在。 + +这同时意味着,如果你有一个没有参数的方法,你依旧必须拥有一个参数——`self`。 + +## 类 + +最简单的类(Class)可以通过下面的案例来展示(保存为 `oop_simplestclass.py`): + +```python +class Person: + pass # 一个空的代码块 + +p = Person() +print(p) + +``` + +输出: + +```python +$ python oop_simplestclass.py +<__main__.Person instance at 0x10171f518> + +``` + +**它是如何工作的** + +我们通过使用 `class` 语句与这个类的名称来创建一个新类。在它之后是一个缩进的语句块,代表这个类的主体。在本案例中,我们创建的是一个空代码块,使用 `pass` 语句予以标明。 + +然后,我们通过采用类的名称后跟一对括号的方法,给这个类创建一个对象(或是实例,我们将在[后面的章节](14.oop.md#init)中了解有关实例的更多内容)。为了验证我们的操作是否成功,我们通过直接将它们打印出来来确认变量的类型。结果告诉我们我们在 `Person` 类的 `__main__` 模块中拥有了一个实例。 + +要注意到在本例中还会打印出计算机内存中存储你的对象的地址。案例中给出的地址会与你在你的电脑上所能看见的地址不相同,因为 Python 会在它找到的任何空间来存储对象。 + +## 方法 + +我们已经在前面讨论过类与对象一如函数那般都可以带有方法(Method),唯一的不同在于我们还拥有一个额外的 `self` 变量。现在让我们来看看下面的例子(保存为 `oop_method.py`)。 + +```python +class Person: + def say_hi(self): + print('Hello, how are you?') + +p = Person() +p.say_hi() +# 前面两行同样可以写作 +# Person().say_hi() +``` + +输出: + +``` +$ python oop_method.py +Hello, how are you? + +``` + +**它是如何工作的** + +这里我们就能看见 `self` 是如何行动的了。要注意到 `say_hi` 这一方法不需要参数,但是依旧在函数定义中拥有 `self` 变量。 + +## `__init__` 方法 + +在 Python 的类中,有不少方法的名称具有着特殊的意义。现在我们要了解的就是 `__init__` 方法的意义。 + +`__init__` 方法会在类的对象被实例化(Instantiated)时立即运行。这一方法可以对任何你想进行操作的目标对象进行\*初始化(Initialization)\*操作。这里你要注意在 init 前后加上的双下划线。 + +案例(保存为 `oop_init.py`): + +```python +class Person: + def __init__(self, name): + self.name = name + + def say_hi(self): + print('Hello, my name is', self.name) + +p = Person('Swaroop') +p.say_hi() +# 前面两行同时也能写作 +# Person('Swaroop').say_hi() +``` + +输出: + +``` +$ python oop_init.py +Hello, my name is Swaroop + +``` + +**它是如何工作的** + +在本例中,我们定义一个接受 `name` 参数(当然还有 `self` 参数)的 `__init__` 方法。在这里,我们创建了一个字段,同样称为 `name`。要注意到尽管它们的名字都是“name”,但这是两个不相同的变量。虽说如此,但这并不会造成任何问题,因为 `self.name` 中的点号意味着这个叫作“name”的东西是某个叫作“self”的对象的一部分,而另一个 `name` 则是一个局部变量。由于我们已经如上这般明确指出了我们所指的是哪一个名字,所以它不会引发混乱。 + +当我们在 `Person` 类下创建新的实例 `p` 时,我们采用的方法是先写下类的名称,后跟括在括号中的参数,形如:`p = Person('Swaroop')`。 + +我们不会显式地调用 `__init__` 方法。 这正是这个方法的特殊之处所在。 + +现在,我们可以使用我们方法中的 `self.name` 字段了,使用的方法在 `say_hi` 方法中已经作过说明。 + +## 类变量与对象变量 {#class-obj-vars} + +我们已经讨论过了类与对象的功能部分(即方法),现在让我们来学习它们的数据部分。数据部分——也就是字段——只不过是\_绑定(Bound)_到类与对象的\*\*命名空间(Namespace)\*\*的普通变量。这就代表着这些名称仅在这些类与对象所存在的上下文中有效。这就是它们被称作_“命名空间”\_的原因。 + +\_字段(Field)\_有两种类型——类变量与对象变量,它们根据究竟是类还是对象\_拥有\_这些变量来进行分类。 + +**类变量(Class Variable)**是共享的(Shared)——它们可以被属于该类的所有实例访问。该类变量只拥有一个副本,当任何一个对象对类变量作出改变时,发生的变动将在其它所有实例中都会得到体现。 + +**对象变量(Object variable)**由类的每一个独立的对象或实例所拥有。在这种情况下,每个对象都拥有属于它自己的字段的副本,也就是说,它们不会被共享,也不会以任何方式与其它不同实例中的相同名称的字段产生关联。下面一个例子可以帮助你理解(保存为 `oop_objvar.py`): + +```python +# coding=UTF-8 + +class Robot: + """表示有一个带有名字的机器人。""" + + # 一个类变量,用来计数机器人的数量 + population = 0 + + def __init__(self, name): + """初始化数据""" + self.name = name + print("(Initializing {})".format(self.name)) + + # 当有人被创建时,机器人 + # 将会增加人口数量 + Robot.population += 1 + + def die(self): + """我挂了。""" + print("{} is being destroyed!".format(self.name)) + + Robot.population -= 1 + + if Robot.population == 0: + print("{} was the last one.".format(self.name)) + else: + print("There are still {:d} robots working.".format( + Robot.population)) + + def say_hi(self): + """来自机器人的诚挚问候 + + 没问题,你做得到。""" + print("Greetings, my masters call me {}.".format(self.name)) + + @classmethod + def how_many(cls): + """打印出当前的人口数量""" + print("We have {:d} robots.".format(cls.population)) + + +droid1 = Robot("R2-D2") +droid1.say_hi() +Robot.how_many() + +droid2 = Robot("C-3PO") +droid2.say_hi() +Robot.how_many() + +print("\nRobots can do some work here.\n") + +print("Robots have finished their work. So let's destroy them.") +droid1.die() +droid2.die() + +Robot.how_many() + +``` + +输出: + +```python +$ python oop_objvar.py +(Initializing R2-D2) +Greetings, my masters call me R2-D2. +We have 1 robots. +(Initializing C-3PO) +Greetings, my masters call me C-3PO. +We have 2 robots. + +Robots can do some work here. + +Robots have finished their work. So let's destroy them. +R2-D2 is being destroyed! +There are still 1 robots working. +C-3PO is being destroyed! +C-3PO was the last one. +We have 0 robots. + +``` + +**它是如何工作的** + +这是一个比较长的案例,但是它有助于展现类与对象变量的本质。在本例中,`population` 属于 `Robot` 类,因此它是一个类变量。`name` 变量属于一个对象(通过使用 `self` 分配),因此它是一个对象变量。 + +因此,我们通过 `Robot.population` 而非 `self.population` 引用 `population` 类变量。我们对于 `name` 对象变量采用 `self.name` 标记法加以称呼,这是这个对象中所具有的方法。要记住这个类变量与对象变量之间的简单区别。同时你还要注意当一个对象变量与一个类变量名称相同时,类变量将会被隐藏。 + +除了 `Robot.popluation`,我们还可以使用 `self.__class__.population`,因为每个对象都通过 `self.__class__` 属性来引用它的类。 + +`how_many` 实际上是一个属于类而非属于对象的方法。这就意味着我们可以将它定义为一个 `classmethod(类方法)` 或是一个 `staticmethod(静态方法)`,这取决于我们是否需要知道这一方法属于哪个类。由于我们已经引用了一个类变量,因此我们使用 `classmethod(类方法)`。 + +我们使用[装饰器(Decorator)](18.more.md#decorator)将 `how_many` 方法标记为类方法。 + +你可以将装饰器想象为调用一个包装器(Wrapper)函数的快捷方式,因此启用 `@classmethod` 装饰器等价于调用: + +```python +how_many = classmethod(how_many) +``` + +你会观察到 `__init__` 方法会使用一个名字以初始化 `Robot` 实例。在这一方法中,我们将 `population` 按 1 往上增长,因为我们多增加了一台机器人。你还会观察到 `self.name` 的值是指定给每个对象的,这体现了对象变量的本质。 + +你需要记住你_只能_使用 `self` 来引用同一对象的变量与方法。这被称作_属性引用(Attribute Reference)_。 + +在本程序中,我们还会看见针对类和方法的 _文档字符串(DocStrings)_ 的使用方式。我们可以在运行时通过 `Robot.__doc__` 访问类的 文档字符串,对于方法的文档字符串,则可以使用 `Robot.say_hi.__doc__`。 + +在 `die` 方法中,我们简单地将 `Robot.population` 的计数按 1 向下减少。 + +所有的类成员都是公开的。但有一个例外:如果你使用数据成员并在其名字中\_使用双下划线作为前缀\_,形成诸如 `__privatevar` 这样的形式,Python 会使用名称调整(Name-mangling)来使其有效地成为一个私有变量。 + +因此,你需要遵循这样的约定:任何在类或对象之中使用的变量其命名应以下划线开头,其它所有非此格式的名称都将是公开的,并可以为其它任何类或对象所使用。请记得这只是一个约定,Python 并不强制如此(除了双下划线前缀这点)。 + +> **针对 C++/Java/C# 程序员的提示** +> +> 所有类成员(包括数据成员)都是\_公开的\_,并且 Python 中所有的方法都是\_虚拟的(Virtual)\_。 + +## 继承 + +面向对象编程的一大优点是对代码的**重用(Reuse)**,重用的一种实现方法就是通过\*\*继承(Inheritance)**机制。继承最好是想象成在类之间实现**类型与子类型(Type and Subtype)\*\*关系的工具。 + +现在假设你希望编写一款程序来追踪一所大学里的老师和学生。有一些特征是他们都具有的,例如姓名、年龄和地址。另外一些特征是他们独有的,一如教师的薪水、课程与假期,学生的成绩和学费。 + +你可以为每一种类型创建两个独立的类,并对它们进行处理。但增添一条共有特征就意味着将其添加进两个独立的类。这很快就会使程序变得笨重。 + +一个更好的方法是创建一个公共类叫作 `SchoolMember`,然后让教师和学生从这个类中\_继承(Inherit)\_,也就是说他们将成为这一类型(类)的子类型,而我们就可以向这些子类型中添加某些该类独有的特征。 + +这种方法有诸多优点。如果我们增加或修改了 `SchoolMember` 的任何功能,它将自动反映在子类型中。举个例子,你可以通过简单地向 SchoolMember 类进行操作,来为所有老师与学生添加一条新的 ID 卡字段。不过,对某一子类型作出的改动并不会影响到其它子类型。另一大优点是你可以将某一老师或学生对象看作 `SchoolMember` 的对象并加以引用,这在某些情况下会大为有用,例如清点学校中的成员数量。这被称作**多态性(Polymorphism)**,在任何情况下,如果父类型希望,子类型都可以被替换,也就是说,该对象可以被看作父类的实例。 + +同时还需要注意的是我们重用父类的代码,但我们不需要再在其它类中重复它们,当我们使用独立类型时才会必要地重复这些代码。 + +在上文设想的情况中,`SchoolMember` 类会被称作**基类(Base Class)**或是**超类(Superclass)**。`Teacher` 和 `Student` 类会被称作**派生类(Derived Classes)**或是**子类(Subclass)**。 + +我们将通过下面的程序作为案例来进行了解(保存为 `oop_subclass.py`): + +```python +# coding=UTF-8 + +class SchoolMember: + '''代表任何学校里的成员。''' + def __init__(self, name, age): + self.name = name + self.age = age + print('(Initialized SchoolMember: {})'.format(self.name)) + + def tell(self): + '''告诉我有关我的细节。''' + print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ") + + +class Teacher(SchoolMember): + '''代表一位老师。''' + def __init__(self, name, age, salary): + SchoolMember.__init__(self, name, age) + self.salary = salary + print('(Initialized Teacher: {})'.format(self.name)) + + def tell(self): + SchoolMember.tell(self) + print('Salary: "{:d}"'.format(self.salary)) + + +class Student(SchoolMember): + '''代表一位学生。''' + def __init__(self, name, age, marks): + SchoolMember.__init__(self, name, age) + self.marks = marks + print('(Initialized Student: {})'.format(self.name)) + + def tell(self): + SchoolMember.tell(self) + print('Marks: "{:d}"'.format(self.marks)) + +t = Teacher('Mrs. Shrividya', 40, 30000) +s = Student('Swaroop', 25, 75) + +# 打印一行空白行 +print() + +members = [t, s] +for member in members: + # 对全体师生工作 + member.tell() +``` + +输出: + +```python +$ python oop_subclass.py +(Initialized SchoolMember: Mrs. Shrividya) +(Initialized Teacher: Mrs. Shrividya) +(Initialized SchoolMember: Swaroop) +(Initialized Student: Swaroop) + +Name:"Mrs. Shrividya" Age:"40" Salary: "30000" +Name:"Swaroop" Age:"25" Marks: "75" +``` + +**它是如何工作的** + +要想使用继承,在定义类时我们需要在类后面跟一个包含基类名称的元组。然后,我们会注意到基类的 `__init__` 方法是通过 `self` 变量被显式调用的,因此我们可以初始化对象的基类部分。下面这一点很重要,需要牢记——因为我们在 `Teacher` 和 `Student` 子类中定义了 `__init__` 方法,Python 不会自动调用基类 `SchoolMember` 的构造函数,你必须自己显式地调用它。 + +相反,如果我们\_没有\_在一个子类中定义一个 `__init__` 方法,Python 将会自动调用基类的构造函数。 + +我们会观察到,我们可以通过在方法名前面加上基类名作为前缀,再传入 `self` 和其余变量,来调用基类的方法。 + +在这里你需要注意,当我们使用 `SchoolMember` 类的 `tell` 方法时,我们可以将 `Teacher` 或 `Student` 的实例看作 `SchoolMember` 的实例。 + +同时,你会发现被调用的是子类型的 `tell` 方法,而不是 `SchoolMember` 的 `tell` 方法。理解这一问题的一种思路是 Python _总会_从当前的实际类型中开始寻找方法,在本例中即是如此。如果它找不到对应的方法,它就会在该类所属的基本类中依顺序逐个寻找属于基本类的方法,这个基本类是在定义子类时后跟的元组指定的。 + +这里有一条有关术语的注释——如果继承元组(Inheritance Tuple)中有超过一个类,这种情况就会被称作**多重继承(Multiple Inheritance)**。 + +`end` 参数用在超类的 `tell()` 方法的 `print` 函数中,目的是打印一行并允许下一次打印在同一行继续。这是一个让 `print` 能够不在打印的末尾打印出 (新行换行符)符号的小窍门。 + +## 总结 + +我们已经探索了有关类和对象的各个方面,还有与它们相关的各类术语。我们还了解了面向对象编程的益处与陷阱。Python 是高度面向对象的,从长远来看,了解这些概念对你大有帮助。 + +接下来,我们将学习如何处理输入与输出,以及如何在 Python 中访问文件。 + +*** + +1. 沈洁元译本译作“封装与解封装”。 +2. 沈洁元译本译作“基本类”。 +3. 此处的类即派生类或子类。 diff --git a/15.io.md b/15.io.md new file mode 100644 index 00000000..78b00f56 --- /dev/null +++ b/15.io.md @@ -0,0 +1,224 @@ +# 输入与输出 + +有些时候你的程序会与用户产生交互。举个例子,你会希望获取用户的输入内容,并向用户打印出一些返回的结果。我们可以分别通过 `input()` 函数与 `print` 函数来实现这一需求。 + +对于输入,我们还可以使用 `str` (String,字符串)类的各种方法。例如,你可以使用 `rjust` 方法来获得一个右对齐到指定宽度的字符串。你可以查看 `help(str)` 来了解更多细节。 + +另一个常见的输入输出类型是处理文件。创建、读取与写入文件对于很多程序来说是必不可少的功能,而我们将在本章探讨这一方面。 + +## 用户输入内容 + +将以下程序保存为 `io_input.py`: + +```python +def reverse(text): + return text[::-1] + + +def is_palindrome(text): + return text == reverse(text) + + +something = input("Enter text: ") +if is_palindrome(something): + print("Yes, it is a palindrome") +else: + print("No, it is not a palindrome") + +``` + +输出: + +```python +$ python3 io_input.py +Enter text: sir +No, it is not a palindrome + +$ python3 io_input.py +Enter text: madam +Yes, it is a palindrome + +$ python3 io_input.py +Enter text: racecar +Yes, it is a palindrome + +``` + +**它是如何工作的** + +我们使用切片功能翻转文本。我们已经了解了我们可以通过使用 `seq[a:b]` 来从位置 `a` 开始到位置 `b` 结束来[对序列进行切片](12.data\_structures.md#sequence) 。我们同样可以提供第三个参数来确定切片的\_步长(Step)\_。默认的步长为 `1`,它会返回一份连续的文本。如果给定一个负数步长,如 `-1`,将返回翻转过的文本。 + +`input()` 函数可以接受一个字符串作为参数,并将其展示给用户。尔后它将等待用户输入内容或敲击返回键。一旦用户输入了某些内容并敲下返回键,`input()` 函数将返回用户输入的文本。 + +我们获得文本并将其进行翻转。如果原文本与翻转后的文本相同,则判断这一文本是[回文](http://en.wiktionary.org/wiki/palindrome)。 + +### 作业练习 + +要想检查文本是否属于回文需要忽略其中的标点、空格与大小写。例如,“Rise to vote, sir.”是一段回文文本,但是我们现有的程序不会这么认为。你可以改进上面的程序以使它能够识别这段回文吗? + +如果你需要一些提示,那么这里有一个想法…… + +## 文件 + +你可以通过创建一个属于 `file` 类的对象并适当使用它的 `read`、`readline`、`write` 方法来打开或使用文件,并对它们进行读取或写入。读取或写入文件的能力取决于你指定以何种方式打开文件。最后,当你完成了文件,你可以调用 `close` 方法来告诉 Python 我们已经完成了对该文件的使用。 + +案例(保存为 `io_using_file.py`): + +```python +poem = '''\ +Programming is fun +When the work is done +if you wanna make your work also fun: + use Python! +''' + +# 打开文件以编辑('w'riting) +f = open('poem.txt', 'w') +# 向文件中编写文本 +f.write(poem) +# 关闭文件 +f.close() + +# 如果没有特别指定, +# 将假定启用默认的阅读('r'ead)模式 +f = open('poem.txt') +while True: + line = f.readline() + # 零长度指示 EOF + if len(line) == 0: + break + # 每行(`line`)的末尾 + # 都已经有了换行符 + #因为它是从一个文件中进行读取的 + print(line, end='') +# 关闭文件 +f.close() + +``` + +输出: + +``` +$ python3 io_using_file.py +Programming is fun +When the work is done +if you wanna make your work also fun: + use Python! + +``` + +**它是如何工作的** + +首先,我们使用内置的 `open` 函数并指定文件名以及我们所希望使用的打开模式来打开一个文件。打开模式可以是阅读模式(`'r'`),写入模式(`'w'`)和追加模式(`'a'`)。我们还可以选择是通过文本模式(`'t'`)还是二进制模式(`'b'`)来读取、写入或追加文本。实际上还有其它更多的模式可用,`help(open)` 会给你有关它们的更多细节。在默认情况下,`open()` 会将文件视作文本(**t**ext)文件,并以阅读(**r**ead)模式打开它。 + +在我们的案例中,我们首先采用写入模式打开文件并使用文件对象的 `write` 方法来写入文件,并在最后通过 `close` 关闭文件。 + +接下来,我们重新在阅读模式下打开同一个文件。我们不需要特别指定某种模式,因为“阅读文本文件”是默认的。我们在循环中使用 `readline` 方法来读取文件的每一行。这一方法将会一串完整的行,其中在行末尾还包含了换行符。当一个\_空\_字符串返回时,它表示我们已经到达了文件末尾,并且通过 `break` 退出循环。 + +最后,我们通过 `close` 关闭了文件。 + +现在,你可以检查 `poem.txt` 文件的内容来确认程序确实对该文件进行了写入与读取操作。 + +## Pickle + +Python 提供了一个叫作 `Pickle` 的标准模块,通过它你可以将\_任何\_纯 Python 对象存储到一个文件中,并在稍后将其取回。这叫作\*持久地(Persistently)\*存储对象。 + +案例(保存为 `io_pickle.py`): + +```python +import pickle + +# 我们存储相关对象的文件的名称 +shoplistfile = 'shoplist.data' +# 需要购买的物品清单 +shoplist = ['apple', 'mango', 'carrot'] + +# 准备写入文件 +f = open(shoplistfile, 'wb') +# 转储对象至文件 +pickle.dump(shoplist, f) +f.close() + +# 清除 shoplist 变量 +del shoplist + +# 重新打开存储文件 +f = open(shoplistfile, 'rb') +# 从文件中载入对象 +storedlist = pickle.load(f) +print(storedlist) + +``` + +输出: + +``` +$ python io_pickle.py +['apple', 'mango', 'carrot'] + +``` + +**它是如何工作的** + +要想将一个对象存储到一个文件中,我们首先需要通过 `open` 以写入(**w**rite)二进制(**b**inary)模式打开文件,然后调用 `pickle` 模块的 `dump` 函数。这一过程被称作\_封装(Pickling)\_。 + +接着,我们通过 `pickle` 模块的 `load` 函数接收返回的对象。这个过程被称作\_拆封(Unpickling)\_。 + +## Unicode[^1] + +截止到现在,当我们编写或使用字符串、读取或写入某一文件时,我们用到的只是简单的英语字符。 + +> 注意:如果你正在使用 Python 2,我们又希望能够读写其它非英语语言,我们需要使用 `unicode` 类型,它全都以字母 `u` 开头,例如 `u"hello world"`。 + +```python +>>> "hello world" +'hello world' +>>> type("hello world") + +>>> u"hello world" +'hello world' +>>> type(u"hello world") + +``` + +当我们阅读或写入某一文件或当我们希望与互联网上的其它计算机通信时,我们需要将我们的 Unicode 字符串转换至一个能够被发送和接收的格式,这个格式叫作“UTF-8”。我们可以在这一格式下进行读取与写入,只需使用一个简单的关键字参数到我们的标准 `open` 函数中: + +```python +# encoding=utf-8 +import io + +f = io.open("abc.txt", "wt", encoding="utf-8") +f.write(u"Imagine non-English language here") +f.close() + +text = io.open("abc.txt", encoding="utf-8").read() +print(text) + +``` + +**它是如何工作的** + +现在你可以忽略 `import` 语句,我们会在[模块章节](11.modules.md#modules)章节探讨有关它的更多细节。 + +每当我们诸如上面那番使用 Unicode 字面量编写一款程序时,我们必须确保 Python 程序已经被告知我们使用的是 UTF-8,因此我们必须将 `# encoding=utf-8` 这一注释放置在我们程序的顶端。 + +我们使用 `io.open` 并提供了“编码(Encoding)”与“解码(Decoding)”参数来告诉 Python 我们正在使用 Unicode。 + +你可以阅读以下文章来了解有关这一话题的更多内容: + +* ["The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets"](http://www.joelonsoftware.com/articles/Unicode.html) +* [Python Unicode Howto](http://docs.python.org/3/howto/unicode.html) +* [Pragmatic Unicode talk by Nat Batchelder](http://nedbatchelder.com/text/unipain.html) + +## 总结 + +我们已经讨论了有关输入和输出的多种类型,这些内容有关文件处理,有关 pickle 模块还有关于 Unicode。 + +接下来,我们将探索一些异常的概念。 + +*** + +1. 沈洁元译本将本节标题译作“储存器”,两版原书在本节的标题相同,但是内容已大不相同。 +2. 可能你已经注意到,在前面章节的一些程序文件中开头标注了采用 UTF-8 编码。这是在中文版翻译过程中为了修改程序中使用三引号括起的说明性字符串,同时要保证程序代码能被 Python 正常识别而作出的改动。 + +[^1]: Unicode 有“统一码”“万国码”“国际码”等多种译名。出于交流习惯的考虑,此处全部采用原文。 diff --git a/16.exceptions.md b/16.exceptions.md new file mode 100644 index 00000000..c2ef3d15 --- /dev/null +++ b/16.exceptions.md @@ -0,0 +1,221 @@ +# 异常 + +当你的程序出现例外情况时就会发生异常(Exception)。例如,当你想要读取一个文件时,而那个文件却不存在,怎么办?又或者你在程序执行时不小心把它删除了,怎么办?这些通过使用**异常**来进行处理。 + +类似地,如果你的程序中出现了一些无效的语句该怎么办?Python 将会对此进行处理,**举起(Raises)**它的小手来告诉你哪里出现了一个**错误(Error)**。 + +## 错误 + +你可以想象一个简单的 `print` 函数调用。如果我们把 `print` 误拼成 `Print` 会怎样?你会注意到它的首字母是大写。在这一例子中,Python 会\_抛出(Raise)\_一个语法错误。 + +```python +>>> Print("Hello World") +Traceback (most recent call last): + File "", line 1, in +NameError: name 'Print' is not defined +>>> print("Hello World") +Hello World +``` + +你会注意到一个 `NameError` 错误被抛出,同时 Python 还会打印出检测到的错误发生的位置。这就是一个错误**错误处理器(Error Handler)** 为这个错误所做的事情。 + +## 异常 + +我们将**尝试(Try)**去读取用户的输入内容。按下 `[ctrl-d]` 来看看会发生什么事情。 + +```python +>>> s = input('Enter something --> ') +Enter something --> Traceback (most recent call last): + File "", line 1, in +EOFError +``` + +此处 Python 指出了一个称作 `EOFError` 的错误,代表着它发现了一个\*文件结尾(End of File)\*符号(由 `ctrl-d` 实现)在不该出现的时候出现了。 + +## 处理异常 + +我们可以通过使用 `try..except` 来处理异常状况。一般来说我们会把通常的语句放在 try 代码块中,将我们的错误处理器代码放置在 except 代码块中。 + +案例(保存文 `exceptions_handle.py`): + +```python +try: + text = input('Enter something --> ') +except EOFError: + print('Why did you do an EOF on me?') +except KeyboardInterrupt: + print('You cancelled the operation.') +else: + print('You entered {}'.format(text)) + +``` + +输出: + +``` +# Press ctrl + d +$ python exceptions_handle.py +Enter something --> Why did you do an EOF on me? + +# Press ctrl + c +$ python exceptions_handle.py +Enter something --> ^CYou cancelled the operation. + +$ python exceptions_handle.py +Enter something --> No exceptions +You entered No exceptions + +``` + +**它是如何工作的** + +我们将所有可能引发异常或错误的语句放在 `try` 代码块中,并将相应的错误或异常的处理器(Handler)放在 `except` 子句或代码块中。`except` 子句可以处理某种特定的错误或异常,或者是一个在括号中列出的错误或异常。如果没有提供错误或异常的名称,它将处理\_所有\_错误与异常。 + +要注意到必须至少有一句 `except` 字句与每一句 `try` 字句相关联。不然,有一个 try 代码块又有什么意义? + +如果没有任何错误或异常被处理,那么将调用 Python 默认处理器,它只会终端程序执行并打印出错误信息。我们已经在前面的章节里见过了这种处理方式。 + +你还可以拥有一个 `else` 子句与 `try..except` 代码块相关联。`else` 子句将在没有发生异常的时候执行。 + +在下一个案例中,我们还将了解如何获取异常对象以便我们可以检索其他信息。 + +## 抛出异常 + +你可以通过 `raise` 语句来\_引发\_一次异常,具体方法是提供错误名或异常名以及要\_抛出(Thrown)\_异常的对象。 + +你能够引发的错误或异常必须是直接或间接从属于 `Exception`(异常) 类的派生类。 + +案例(保存为 `exceptions_raise.py`): + +```python +# encoding=UTF-8 + +class ShortInputException(Exception): + '''一个由用户定义的异常类''' + def __init__(self, length, atleast): + Exception.__init__(self) + self.length = length + self.atleast = atleast + +try: + text = input('Enter something --> ') + if len(text) < 3: + raise ShortInputException(len(text), 3) + # 其他工作能在此处继续正常运行 +except EOFError: + print('Why did you do an EOF on me?') +except ShortInputException as ex: + print(('ShortInputException: The input was ' + + '{0} long, expected at least {1}') + .format(ex.length, ex.atleast)) +else: + print('No exception was raised.') + +``` + +输出: + +``` +$ python exceptions_raise.py +Enter something --> a +ShortInputException: The input was 1 long, expected at least 3 + +$ python exceptions_raise.py +Enter something --> abc +No exception was raised. + +``` + +**它是如何工作的** + +在本例中,我们创建了我们自己的异常类型。这一新的异常类型叫作 `ShortInputException`。它包含两个字段——获取给定输入文本长度的 `length`,程序期望的最小长度 `atleast`。 + +在 `except` 子句中,我们提及了错误类,将该类存储 `as(为)` 相应的错误名或异常名。这类似于函数调用中的形参与实参。在这个特殊的 `except` 子句中我们使用异常对象的 `length` 与 `atleast` 字段来向用户打印一条合适的信息。 + +## Try ... Finally + +假设你正在你的读取中读取一份文件。你应该如何确保文件对象被正确关闭,无论是否会发生异常?这可以通过 `finally` 块来完成。 + +保存该程序为 `exceptions_finally.py`: + +```python +import sys +import time + +f = None +try: + f = open("poem.txt") + # 我们常用的文件阅读风格 + while True: + line = f.readline() + if len(line) == 0: + break + print(line, end='') + sys.stdout.flush() + print("Press ctrl+c now") + # 为了确保它能运行一段时间 + time.sleep(2) +except IOError: + print("Could not find file poem.txt") +except KeyboardInterrupt: + print("!! You cancelled the reading from the file.") +finally: + if f: + f.close() + print("(Cleaning up: Closed the file)") + +``` + +输出: + +``` +$ python exceptions_finally.py +Programming is fun +Press ctrl+c now +^C!! You cancelled the reading from the file. +(Cleaning up: Closed the file) + +``` + +**它是如何工作的** + +我们按照通常文件读取进行操作,但是我们同时通过使用 `time.sleep` 函数任意在每打印一行后插入两秒休眠,使得程序运行变得缓慢(在通常情况下 Python 运行得非常快速)。当程序在处在运行过过程中时,按下 `ctrl + c` 来中断或取消程序。 + +你会注意到 `KeyboardInterrupt` 异常被抛出,尔后程序退出。不过,在程序退出之前,finally 子句得到执行,文件对象总会被关闭。 + +另外要注意到我们在 `print` 之后使用了 `sys.stout.flush()`,以便它能被立即打印到屏幕上。 + +## `with` 语句 + +在 `try` 块中获取资源,然后在 `finally` 块中释放资源是一种常见的模式。因此,还有一个 `with` 语句使得这一过程可以以一种干净的姿态得以完成。 + +保存为 `exceptions_using_with.py`: + +```python +with open("poem.txt") as f: + for line in f: + print(line, end='') + +``` + +**它是如何工作的** + +程序输出的内容应与上一个案例所呈现的相同。本例的不同之处在于我们使用的是 `open` 函数与 `with` 语句——我们将关闭文件的操作交由 `with open` 来自动完成。 + +在幕后发生的事情是有一项 `with` 语句所使用的协议(Protocol)。它会获取由 `open` 语句返回的对象,在本案例中就是“thefile”。 + +它\_总会\_在代码块开始之前调用 `thefile.__enter__` 函数,并且\_总会\_在代码块执行完毕之后调用 `thefile.__exit__`。 + +因此,我们在 `finally` 代码块中编写的代码应该格外留心 `__exit__` 方法的自动操作。这能够帮助我们避免重复显式使用 `try..finally` 语句。 + +有关该话题的更多讨论已经超出了本书所能涉及的范围,因此请参考 [PEP 343](http://www.python.org/dev/peps/pep-0343/) 来了解更加全面的解释。 + +## 总结 + +我们已经讨论了 `try..except` 和 `try..finally` 语句的用法。同时我们也已经看到了如何创建我们自己的异常类型,还有如何抛出异常。 + +接下来,我们将探索 Python 的标准库。 + +*** + +1. 此处采用沈洁元译本的翻译。但是在其它教程或有关 Python 的讨论文章中,Handler 大都保留原文而不作翻译,这点需读者知悉。 diff --git a/17.stdlib.md b/17.stdlib.md new file mode 100644 index 00000000..4a80235c --- /dev/null +++ b/17.stdlib.md @@ -0,0 +1,100 @@ +# 标准库 + +Python 标准库(Python Standrad Library)中包含了大量有用的模块,同时也是每个标准的 Python 安装包中的一部分。熟悉 Python 标准库十分重要,因为只要你熟知这些库可以做到什么事,许多问题都能够轻易解决。 + +我们将探索这个库中的一些常用模块。你能在你的 Python 安装包中附带的文档中的[“库概览(Library Reference)” 部分](http://docs.python.org/3/library/)中查找到所有模块的全部细节。 + +让我们来了解一些有用的模块。 + +> \*\*注意:\*\*如果你觉得本章内容过于超前,你可以先跳过本章。不过,我强烈建议你在适应了采用 Python 进行编程后再来看看本章。 + +## `sys` 模块 + +`sys` 模块包括了一些针对特定系统的功能。我们已经了解过 `sys.argv` 列表中包括了命令行参数。 + +想象一些我们需要检查正在使用的 Python 软件的版本,`sys` 模块会给我们相关的信息。 + +```python +>>> import sys +>>> sys.version_info +sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0) +>>> sys.version_info.major == 3 +True +``` + +**它是如何工作的** + +`sys` 模块包含一个 `version_info` 元组,它提供给我们版本信息。第一个条目是主版本信息。我们可以调出这些信息并使用它。 + +## 日志模块 + +如果你想将一些调试(Debugging)信息或一些重要的信息储存在某个地方,以便你可以检查你的程序是否如你所期望那般运行,应该怎么做?你应该如何将这些信息“储存在某个地方”?这可以通过 `logging` 模块来实现。 + +保存为 `stdlib_logging.py`: + +```python +import os +import platform +import logging + +if platform.platform().startswith('Windows'): + logging_file = os.path.join(os.getenv('HOMEDRIVE'), + os.getenv('HOMEPATH'), + 'test.log') +else: + logging_file = os.path.join(os.getenv('HOME'), + 'test.log') + +print("Logging to", logging_file) + +logging.basicConfig( + level=logging.DEBUG, + format='%(asctime)s : %(levelname)s : %(message)s', + filename=logging_file, + filemode='w', +) + +logging.debug("Start of the program") +logging.info("Doing something") +logging.warning("Dying now") + +``` + +输出: + +``` +$ python stdlib_logging.py +Logging to /Users/swa/test.log + +$ cat /Users/swa/test.log +2014-03-29 09:27:36,660 : DEBUG : Start of the program +2014-03-29 09:27:36,660 : INFO : Doing something +2014-03-29 09:27:36,660 : WARNING : Dying now + +``` + +如果你不能运行 `cat` 命令,你可以通过一款文本编辑器打开 `test.log` 文件。 + +**它是如何工作的** + +我们使用了三款标准库中的模块——`os` 模块用以和操作系统交互,`platform` 模块用以获取平台——操作系统——的信息,`logging` 模块用来\*记录(Log)\*信息。 + +首先,我们通过检查 `platform.platform()` 返回的字符串来确认我们正在使用的操作系统(有关更多信息,请参阅`import platform; help(platform)`)。如果它是 Windows,我们将找出其主驱动器(Home Drive),主文件夹(Home Folder)以及我们希望存储信息的文件名。将这三个部分汇聚到一起,我们得到了有关文件的全部位置信息。对于其它平台而言,我们需要知道的只是用户的主文件夹位置,这样我们就可获得文件的全部位置信息。 + +我们使用 `os.path.join()` 函数来将这三部分位置信息聚合到一起。使用这一特殊函数,而非仅仅将这几段字符串拼凑在一起的原因是这个函数会确保完整的位置路径符合当前操作系统的预期格式。 + +然后我们配置 `logging` 模块,让它以特定的格式将所有信息写入我们指定的文件。 + +最后,无论这些信息是用以调试,提醒,警告甚至是其它关键的消息,我们都可以将其聚合并记录。一旦程序开始运行,我们可以检查这一文件,从而我们便能知道程序运行过程中究竟发生了什么,哪怕在用户运行时什么信息都没有显示。 + +## 每周模块系列 + +标准库中还有许多模块值得探索,例如一些[用以调试(Debugging)的模块](http://docs.python.org/3/library/pdb.html), [处理命令行选项的模块](http://docs.python.org/3/library/argparse.html),[正则表达式(Regular Expressions)模块](http://docs.python.org/3/library/re.html) 等等等等。 + +进一步探索标准库的最好方法是阅读由 Doug Hellmann 撰写的优秀的 [Python Module of the Week](http://pymotw.com/2/contents.html) 系列(你还可以阅读[它的实体书](http://amzn.com/0321767349)或是阅读 [Python 官方文档](http://docs.python.org/3/))。 + +## 总结 + +我们已经探索了 Python 标准库中提供的诸多的模块的一些功能。在此强烈建议你浏览 [Python 标准库文档](http://docs.python.org/3/library/)来了解所有可以使用的模块。 + +接下来,我们将介绍 Python 的其它各个方面,让我们的 Python 之旅更加\_完整\_。 diff --git a/18.more.md b/18.more.md new file mode 100644 index 00000000..785869f3 --- /dev/null +++ b/18.more.md @@ -0,0 +1,247 @@ +# 更多 + +到现在,我们的介绍已经涵盖了你将使用到的 Python 的大部分方面。在本章中,我们将介绍一些其它的方面,来让我们对 Python 的认识更加全面。 + +## 传递元组 + +你可曾希望从一个函数中返回两个不同的值?你能做到的。只需要使用一个元组。 + +```python +>>> def get_error_details(): +... return (2, 'details') +... +>>> errnum, errstr = get_error_details() +>>> errnum +2 +>>> errstr +'details' +``` + +要注意到 `a, b = ` 的用法会将表达式的结果解释为具有两个值的一个元组。 + +这也意味着在 Python 中交换两个变量的最快方法是: + +```python +>>> a = 5; b = 8 +>>> a, b +(5, 8) +>>> a, b = b, a +>>> a, b +(8, 5) +``` + +## 特殊方法 + +诸如 `__init__` 和 `__del__` 等一些方法对于类来说有特殊意义。 + +特殊方法用来模拟内置类型的某些行为。举个例子,如果你希望为你的类使用 `x[key]` 索引操作(就像你在列表与元组中使用的那样),那么你所需要做的只不过是实现 `__getitem__()` 方法,然后你的工作就完成了。如果你试图理解它,就想想 Python 就是对 `list` 类这样做的! + +下面的表格列出了一些有用的特殊方法。如果你想了解所有的特殊方法,请[参阅手册](http://docs.python.org/3/reference/datamodel.html#special-method-names)。 + +* `__init__(self, ...)` + * 这一方法在新创建的对象被返回准备使用时被调用。 +* `__del__(self)` + * 这一方法在对象被删除之前调用(它的使用时机不可预测,所以避免使用它) +* `__str__(self)` + * 当我们使用 `print` 函数时,或 `str()` 被使用时就会被调用。 +* `__lt__(self, other)` + * 当\_小于\_运算符(<)被使用时被调用。类似地,使用其它所有运算符(+、> 等等)时都会有特殊方法被调用。 +* `__getitem__(self, key)` + * 使用 `x[key]` 索引操作时会被调用。 +* `__len__(self)` + * 当针对序列对象使用内置 `len()` 函数时会被调用 + +## 单语句块 + +我们已经见识过每一个语句块都由其自身的缩进级别与其它部分相区分。 是这样没错,不过有一个小小的警告。如果你的语句块只包括单独的一句语句,那么你可以在同一行指定它,例如条件语句与循环语句。下面这个例子应该能比较清楚地解释: + +```python +>>> flag = True +>>> if flag: print('Yes') +... +Yes +``` + +注意,单个语句是在原地立即使用的,它不会被看作一个单独的块。尽管,你可以通过这种方式来使你的程序更加\_小巧\_,但除非是为了检查错误,我强烈建议你避免使用这种快捷方法,这主要是因为如果你不小心使用了一个“恰到好处”的缩进,它就很容易添加进额外的语句。 + +## Lambda 表格 + +`lambda` 语句可以创建一个新的函数对象。从本质上说,`lambda` 需要一个参数,后跟一个表达式作为函数体,这一表达式执行的值将作为这个新函数的返回值。 + +案例(保存为 `more_lambda.py`): + +```python +points = [{'x': 2, 'y': 3}, + {'x': 4, 'y': 1}] +points.sort(key=lambda i: i['y']) +print(points) + +``` + +输出: + +``` +$ python more_lambda.py +[{'y': 1, 'x': 4}, {'y': 3, 'x': 2}] + +``` + +**它是如何工作的** + +要注意到一个 `list` 的 `sort` 方法可以获得一个 `key` 参数,用以决定列表的排序方式(通常我们只知道升序与降序)。在我们的案例中,我们希望进行一次自定义排序,为此我们需要编写一个函数,但是又不是为函数编写一个独立的 `def` 块,只在这一个地方使用,因此我们使用 Lambda 表达式来创建一个新函数。 + +## 列表推导 + +列表推导(List Comprehension)用于从一份现有的列表中得到一份新列表。想象一下,现在你已经有了一份数字列表,你想得到一个相应的列表,其中的数字在大于 2 的情况下将乘以 2。列表推导就是这类情况的理想选择。 + +案例(保存为 `more_list_comprehension.py`): + +```python +listone = [2, 3, 4] +listtwo = [2*i for i in listone if i > 2] +print(listtwo) + +``` + +输出: + +``` +$ python more_list_comprehension.py +[6, 8] + +``` + +**它是如何工作的** + +在本案例中,当满足了某些条件时(`if i > 2`),我们进行指定的操作(`2*i`),以此来获得一份新的列表。要注意到原始列表依旧保持不变。 + +使用列表推导的优点在于,当我们使用循环来处理列表中的每个元素并将其存储到新的列表中时时,它能减少样板(Boilerplate)代码的数量。 + +## 在函数中接收元组与字典 + +有一种特殊方法,即分别使用 `*` 或 `**` 作为元组或字典的前缀,来使它们作为一个参数为函数所接收。当函数需要一个可变数量的实参时,这将颇为有用。 + +```python +>>> def powersum(power, *args): +... '''Return the sum of each argument raised to the specified power.''' +... total = 0 +... for i in args: +... total += pow(i, power) +... return total +... +>>> powersum(2, 3, 4) +25 +>>> powersum(2, 10) +100 +``` + +因为我们在 `args` 变量前添加了一个 `*` 前缀,函数的所有其它的额外参数都将传递到 `args` 中,并作为一个元组予以储存。如果采用的是 `**` 前缀,则额外的参数将被视为字典的键值—值配对。 + +## `assert` 语句 + +`assert` 语句用以断言(Assert)某事是真的。例如说你非常确定你正在使用的列表中至少包含一个元素,并想确认这一点,如果其不是真的,就抛出一个错误,`assert` 语句就是这种情况下的理想选择。当语句断言失败时,将会抛出 `AssertionError`。 + +```python +>>> mylist = ['item'] +>>> assert len(mylist) >= 1 +>>> mylist.pop() +'item' +>>> assert len(mylist) >= 1 +Traceback (most recent call last): + File "", line 1, in +AssertionError +``` + +你应该明智地选用 `assert` 语句。在大多数情况下,它好过捕获异常,也好过定位问题或向用户显示错误信息然后退出。 + +## 装饰器 + +装饰器(Decorators)是应用包装函数的快捷方式。这有助于将某一功能与一些代码一遍又一遍地“包装”。举个例子,我为自己创建了一个 `retry` 装饰器,这样我可以将其运用到任何函数之中,如果在一次运行中抛出了任何错误,它就会尝试重新运行,直到最大次数 5 次,并且每次运行期间都会有一定的延迟。这对于你在对一台远程计算机进行网络调用的情况十分有用: + +```python +from time import sleep +from functools import wraps +import logging +logging.basicConfig() +log = logging.getLogger("retry") + + +def retry(f): + @wraps(f) + def wrapped_f(*args, **kwargs): + MAX_ATTEMPTS = 5 + for attempt in range(1, MAX_ATTEMPTS + 1): + try: + return f(*args, **kwargs) + except: + log.exception("Attempt %s/%s failed : %s", + attempt, + MAX_ATTEMPTS, + (args, kwargs)) + sleep(10 * attempt) + log.critical("All %s attempts failed : %s", + MAX_ATTEMPTS, + (args, kwargs)) + return wrapped_f + + +counter = 0 + + +@retry +def save_to_database(arg): + print("Write to a database or make a network call or etc.") + print("This will be automatically retried if exception is thrown.") + global counter + counter += 1 + # 这将在第一次调用时抛出异常 + # 在第二次运行时将正常工作(也就是重试) + if counter < 2: + raise ValueError(arg) + + +if __name__ == '__main__': + save_to_database("Some bad value") + +``` + +输出: + +``` +$ python more_decorator.py +Write to a database or make a network call or etc. +This will be automatically retried if exception is thrown. +ERROR:retry:Attempt 1/5 failed : (('Some bad value',), {}) +Traceback (most recent call last): + File "more_decorator.py", line 14, in wrapped_f + return f(*args, **kwargs) + File "more_decorator.py", line 39, in save_to_database + raise ValueError(arg) +ValueError: Some bad value +Write to a database or make a network call or etc. +This will be automatically retried if exception is thrown. + +``` + +**它是如何工作的** + +请参阅: + +* http://www.ibm.com/developerworks/linux/library/l-cpdecor.html +* http://toumorokoshi.github.io/dry-principles-through-python-decorators.html + +## Python 2 与 Python 3 的不同 + +请参阅: + +* ["Six" library](http://pythonhosted.org/six/) +* [Porting to Python 3 Redux by Armin](http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/) +* [Python 3 experience by PyDanny](http://pydanny.com/experiences-with-django-python3.html) +* [Official Django Guide to Porting to Python 3](https://docs.djangoproject.com/en/dev/topics/python3/) +* [Discussion on What are the advantages to python 3.x?](http://www.reddit.com/r/Python/comments/22ovb3/what\_are\_the\_advantages\_to\_python\_3x/) + +## 总结 + +我们在本章中介绍了有关 Python 的更多功能,不过我们还未涵盖到 Python 的所有功能。不过,在这一阶段,我们已经涉猎了大多数你将在实践中遇到的内容。这足以让你开始编写任何你所期望的程序。 + +接下来,我们将讨论如何进一步探索 Python。 diff --git a/19.what_next.md b/19.what_next.md new file mode 100644 index 00000000..ffefe92f --- /dev/null +++ b/19.what_next.md @@ -0,0 +1,142 @@ +# 迈出下一步 + +如果到现在你已经阅读过本书并且编写了许多程序,那么你一定已经开始熟悉并且习惯 Python 了。或许你已经创建了一些 Python 程序来尝试完成一些工作,同时锻炼你自己的 Python 技能。如果你尚未至此,你也应该作出努力。现在我们面临的问题是“下一步该做什么?”。 + +我会建议你试图解决这个问题: + +> 编写一款你自己的命令行_地址簿_程序,你可以用它浏览、添加、编辑、删除或搜索你的联系人,例如你的朋友、家人、同事,还有他们诸如邮件地址、电话号码等多种信息。这些详细信息必须被妥善储存以备稍后的检索。 + +如果你回想至今我们学过、讨论过、遇见过的所有东西,你会发现这其实非常简单。如果你仍想要有关如何进行的提示,这儿倒是有一些。 + +一旦你能够做到这件事,你便可以说自己是一名 Python 程序员了。现在,赶快\[写封邮件]\(\{{ book.contactUrl \}})来感谢我写出了这么棒的一本书 ;-)。这一步并非强制但我仍建议如此。同时,请考虑\[购买本书的实体书]\(\{{ book.buyBookUrl \}})来支持本书的后续改进。 + +如果你觉得上面的程序太容易了,这还有另一个: + +> 实现[替换命令](http://unixhelp.ed.ac.uk/CGI/man-cgi?replace)。这个命令能将一串字符串替换为另外提供的文件或列表中的另一串。 + +只要你想,替换命令可以或简单或复杂地实现,从简单的字符串替换到搜寻搭配的样式(正则表达式)。 + +## 下一个项目 + +如果你发现上面的程序都能很容易地编写出来,那么看看下面这个完整的项目列表,并尝试编写你自己的程序:https://github.com/thekarangoel/Projects#numbers (这一列表与 [Martyr2 的超级项目列表](http://www.dreamincode.net/forums/topic/78802-martyr2s-mega-project-ideas-list/)相同)。 + +你还可以看看: + +* [Exercises for Programmers: 57 Challenges to Develop Your Coding Skills](https://pragprog.com/book/bhwb/exercises-for-programmers) +* [Intermediate Python Projects](https://openhatch.org/wiki/Intermediate\_Python\_Workshop/Projects) + +## 示例代码 + +学习一门编程语言的最好方式就是编写大量代码,并阅读大量代码: + +* [Python Cookbook](http://code.activestate.com/recipes/langs/python/) 是一本极具价值的“烹饪法”与提示的集合,它介绍了如何通过 Python 解决某些特定类型的问题。 +* [Python Module of the Week](http://pymotw.com/2/contents.html) 是另一本优秀的[标准库](stdlib.md#stdlib)必读指南。 + +## 建议 + +* [The Hitchhiker's Guide to Python!](http://docs.python-guide.org/en/latest/) +* [The Elements of Python Style](https://github.com/amontalenti/elements-of-python-style) +* [Python Big Picture](http://slott-softwarearchitect.blogspot.ca/2013/06/python-big-picture-whats-roadmap.html) +* ["Writing Idiomatic Python" ebook](http://www.jeffknupp.com/writing-idiomatic-python-ebook/) (付费) + +## 视频 + +* [Full Stack Web Development with Flask](https://github.com/realpython/discover-flask) +* [PyVideo](http://www.pyvideo.org) + +## 问与答 + +* [Official Python Dos and Don'ts](http://docs.python.org/3/howto/doanddont.html) +* [Official Python FAQ](http://www.python.org/doc/faq/general/) +* [Norvig's list of Infrequently Asked Questions](http://norvig.com/python-iaq.html) +* [Python Interview Q & A](http://dev.fyicenter.com/Interview-Questions/Python/index.html) +* [StackOverflow questions tagged with python](http://stackoverflow.com/questions/tagged/python) + +## 教程 + +* [Hidden features of Python](http://stackoverflow.com/q/101268/4869) +* [What's the one code snippet/python trick/etc did you wish you knew when you learned python?](http://www.reddit.com/r/Python/comments/19dir2/whats\_the\_one\_code\_snippetpython\_tricketc\_did\_you/) +* [Awaretek's comprehensive list of Python tutorials](http://www.awaretek.com/tutorials.html) + +## 讨论 + +如果你遇到了一个 Python 问题,但不知道该问谁,那么 [python-tutor list](http://mail.python.org/mailman/listinfo/tutor) 是你提问的最佳场所。 + +请确保你会自己做你的家庭作业,你会首先尝试自己解决问题,同时,还要会[问聪明的问题](http://catb.org/\~esr/faqs/smart-questions.html)。 + +## 新闻 + +如果你希望了解 Python 世界的最新动态,那就跟随 [Official Python Planet](http://planet.python.org) 的脚步吧。 + +## 安装库 + +[Python 库索引](http://pypi.python.org/pypi)中包含了大量开源的库,你可以在你自己的程序中使用它们。 + +要想了解如何安装并使用这些库,你可以使用 [pip](http://www.pip-installer.org/en/latest/)。 + +## 创建一个网站 + +学习使用 [Flask](http://flask.pocoo.org) 来创建你自己的网站。下面这些资源有助于你开始学习: + +* [Flask Official Quickstart](http://flask.pocoo.org/docs/quickstart/) +* [The Flask Mega-Tutorial](http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) +* [Example Flask Projects](https://github.com/mitsuhiko/flask/tree/master/examples) + +## 图形软件 + +假设你希望使用 Python 来创建你自己的图形程序。这可以通过采用一个 GUI(Graphical User Interface,图形用户界面)库和它们的 Python 绑定来实现。绑定是允许你用 Python 编写你自己的程序,然后使用它们在 C 或 C++ 或其它语言写编写的库。 + +使用 Python 的 GUI 有许多选择: + +* Kivy + * http://kivy.org +* PyGTK + * 这是 GTK+ 工具包的 Python 绑定,它是构建 GNOME 的基础。GTK+ 有许多奇怪的用法,但是你一旦习惯了使用它,就能很快的创建出你的 GUI 应用。Glade 图形界面设计工具是不可或缺的。它的文档至今仍在不断改进。GTK+ 在 GNU/Linux 下能够良好工作,但是它针对 Windows 平台的移植工作尚未完成。你可以使用 GTK+ 创建免费或专有的软件。要想开始使用,请阅读 [PyGTK 教程](http://www.pygtk.org/tutorial.html)。 +* PyQt - 这是 Qt 工具包的 Python 绑定,它是构建 KDE 的基础。 受益于 Qt Designer 与令人惊讶的 Qt 文档,Qt 十分容易使用也十分强大。如果你希望创建一款开源(GPL)软件,你可以免费使用 PyQt,不过如果你想创建专有的闭源软件,你需要购买它。从 Qt 4.5 开始你可以使用它来创建不采用 GPL 授权的软件。要想开始使用,请阅读 [PySide](http://qt-project.org/wiki/PySide)。 +* wxPython + * 这是 wxWidgets 工具包的 Python 绑定。wxPython 有一个与之相关的学习曲线。不过,它非常便携,并且可以运行在 GNU/Linux、Windwos、Mac、甚至是嵌入式平台中。有许多 IDE 可以采用 wxPython,并且包含了 GUI 设计工具,例如 [SPE (Stani's Python Editor)](http://spe.pycs.net/) 还有 [wxGlade](http://wxglade.sourceforge.net/) GUI 构建工具。你可以使用 wxPython 来创建免费或专有的软件。要想开始使用,请阅读[wxPython 教程](http://zetcode.com/wxpython/)。 + +### GUI 工具总结 + +想要了解更多的选择,可以参阅 [GuiProgramming wiki page at the official python website](http://www.python.org/cgi-bin/moinmoin/GuiProgramming)。 + +不幸的是,Python 没有一款标准 GUI 工具。我建议你根据你的实际情况从上面列出的工具中进行挑选。第一个因素是你是否愿意为使用任何 GUI 工具付费。第二个因素是你希望你的程序只在 Windwos 上运行,还是在 Mac 和 GNU/Linux 上运行,还是在它们三者之上都能运行。第三个因素,如果 GNU/Linux 是目标平台,那你是要做 KDE 用户还是 GNOME 用户。 + +有关更详尽且更全面的分析,请参阅 ['The Python Papers, Volume 3, Issue 1' (PDF)](http://archive.pythonpapers.org/ThePythonPapersVolume3Issue1.pdf) 的第 26 页。 + +## 各种实现 + +编程语言主要有两部分——语言与软件。语言是你\_如何\_编写,软件是你\_怎样\_实际运行我们的程序。 + +我们一直在使用 _CPython_ 软件来运行我们的程序。它被成为 CPython 是因为它是使用 C 语言编写的,同时它也是\_经典的(Classical) Python 解释器\_。 + +还有其他软件可以运行你的 Python 程序: + +* [Jython](http://www.jython.org) + * 在 Java 平台上运行的 Python 实现。这意味着你可以在 Python 语言中使用 Java 的库与类,反之亦然。 +* [IronPython](http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython) + * 在 .NET 平台上运行的 Python 实现。这意味着你可以在 Python 语言中使用 .NET 的库与类,反之亦然 +* [PyPy](http://codespeak.net/pypy/dist/pypy/doc/home.html) + * 用 Python 编写的 Python 实现!这是一项研究项目,旨在于使其能快速且方便的改进解释器,因为解释器本身就是用动态语言编写的了(而不是采用上述三种 C、Java、C# 等动态语言来编写)。 + +还有其它诸如 [CLPython](http://common-lisp.net/project/clpython/)——采用 Common Lisp 编写的 Python 实现,和[Brython](http://brython.info/) ,它在 JavaScript 解释器之上实现,意味着你可以使用 Python(而非 JavaScript)编写你的 Web 浏览器(“Ajax”)程序。 + +上述这些实现每一种都有其大有作为的专门领域。 + +## 函数式编程(面向高阶读者){#functional-programming} + +当你开始编写更加庞大的程序时,你应该清楚了解更多关于使用函数的方式来进行编程,而不是我们在[《面向对象编程》章节中](14.oop.md#oop)所学习的基于类的方式进行编程: + +* [Functional Programming Howto by A.M. Kuchling](http://docs.python.org/3/howto/functional.html) +* [Functional programming chapter in 'Dive Into Python' book](http://www.diveintopython.net/functional\_programming/index.html) +* [Functional Programming with Python presentation](http://ua.pycon.org/static/talks/kachayev/index.html) +* [Funcy library](https://github.com/Suor/funcy) +* [PyToolz library](http://toolz.readthedocs.org/en/latest/) + +## 总结 + +现在我们已经行至本书末尾,不过,正如人们所说,这是_昭示着开始的终结_!你现在已经是一名狂热 Python 用户,毫无疑问,你已准备好通过 Python 来解决诸多问题了。你可以开始自动化你的电脑,去做任何你以前难以想象的事情,你可以开始编写你自己的游戏,开始做更多更多的事,远不仅此。来,让我们出发吧! + +*** + +1. 创建一个类用来表示人的信息。使用一份字典来存储人物对象,将它们的名字当作键值。使用 pickle 模块来将对象长久地存储在硬盘上。使用字典的内置方法来添加、删除或编辑地址簿中的人物。——原书注 diff --git a/20.floss.md b/20.floss.md new file mode 100644 index 00000000..2d2d310c --- /dev/null +++ b/20.floss.md @@ -0,0 +1,41 @@ +# 附录:FLOSS {#floss} + +> 作者注:请注意这一章撰写于 2003 年,所以里面有些内容对你来说可能已显得古早。:-) + +“自由/开放源代码软件”,简称 [FLOSS](http://en.wikipedia.org/wiki/FLOSS),是一个基于社区概念而建立的组织,而这一社区则基于分享、尤其是知识分享这些概念。FLOSS 的成员软件均可免费使用、修改与分发。 + +如果你已经读完本书,那么你对 FLOSS 概念应该已经很熟悉了,因为你正在使用的 *Python* 便是其中一员,而且 Python 还是一款开源软件! + +下面是一些 FLOSS 的案例,可以帮助你了解社区共享共建可以创造出什么样的东西: + +[Linux](http://www.kernel.org):这是一款 FLOSS 操作系统内核,运用于 GNU/Linux 操作系统之中。Linux 这一内核是由 Linus Torvalds 在他还是一名学生时发起的。Android 系统便是基于 Linux。现在你所使用的任何一家网站其中的大部分都运行于 Linux 之上。 + +[Ubuntu](http://www.ubuntu.com):这是一款由 Canonical 赞助、社区驱动的 Linux 发行版,是目前世界上最流行的 GNU/Linux 发行版。它允许你通过一款易于使用且易于安装的管理器安装大量 FLOSS 成员软件。最重要的是,你可以重启计算机然后通过 CD 来运行 GNU/Linux 系统!这一点能够允许你的电脑上安装新的操作系统前对它进行充分的试用。但是,Ubuntu 不是完全的免费软件,它包括了一些专有的驱动程序,固件和应用程序。 + +[LibreOffice](http://www.libreoffice.org/):这是一款基于社区驱动与开发的优秀的办公套件,包括文档写作、演示制作、电子表格和绘图组件等诸多内容。它甚至可以轻松打开并编辑 MS Word 文件和 MS PowerPoint 文件。它能够在几乎所有平台中运行,并且完全免费、自由、开源。 + +[Mozilla Firefox](http://www.mozilla.org/products/firefox):这就是_那一款_最好的网络浏览器。它以速度极快,并且以敏锐且令人印象深刻的功能获得了诸多赞誉。它的扩展概念能够允许用户使用任何种类的插件。 + +[Mono](http://www.mono-project.com):这是一款微软 .NET 平台的开源实现。它能够允许在 GNU/Linux,Windows,FreeBSD,MacOS 等其它诸多平台上创建并使用 .NET 应用程序。 + +[Apache Web 服务器](http://httpd.apache.org):这是一款十分流行的开源 Web 服务器。实际上,它是这个星球上_最_流行的 Web 服务器!在它之上运行着世界上超过一半的网站。是的,正是如此——Apache 的使用量比它的所有对手(包括 Microsoft IIS)加起来还要多。 + +[VLC 播放器](http://www.videolan.org/vlc/):这款视频播放器可以播放从 DivX 到 MP3 到 Ogg 到 VCD 到 DVD 等几乎任何内容。谁说开源没有乐趣的?;-) + +上面这一列表只是为了给你一个简单的印象——还有其它许多优秀的东西在 FLOSS 里等待你的发现,例如 Perl 语言,PHP 语言,针对网站的 Drupal 内容管理系统,PostgreSQL 数据服务器,TORCS 赛车游戏,KDevelop IDE,Xine 电影播放器,VIM 编辑器,Quanta+ 编辑器,Banshee 音频播放器,GIMP 图片编辑程序等等等等,这一列表可以永远不断地罗列下去。 + +要想了解 FLOSS 世界的最新动态,你可以访问以下网站: + +- [OMG! Ubuntu!](http://www.omgubuntu.co.uk/) +- [Web Upd8](http://www.webupd8.org/) +- [DistroWatch](http://www.distrowatch.com) +- [Planet Debian](http://planet.debian.org/) + +浏览下列网站以了解有关 FLOSS 的更多信息: + +- [GitHub Explore](http://github.com/explore) +- [Code Triage](http://www.codetriage.com/) +- [SourceForge](http://www.sourceforge.net) +- [FreshMeat](http://www.freshmeat.net) + +所以,接着走下去吧,去探索这个广阔、自由且开放的 FLOSS 世界! \ No newline at end of file diff --git a/21.about.md b/21.about.md new file mode 100644 index 00000000..36e5e943 --- /dev/null +++ b/21.about.md @@ -0,0 +1,33 @@ +# 附录:版本变迁 {#colophon} + +我为了编写本书而使用的几乎所有软件都属于 [FLOSS](./20.floss.md#floss)。 + +## 本书的诞生 + +在撰写本书的第一版时,我使用 Red Hat 9.0 Linux 作为我配置的基础,到了第六版时,我使用 Fedora Core 3 Linux 作为我配置的基础。 + +最初,我使用 KWord 来撰写本书(正如在[本书由来](./22.revision_history.md#history-lesson)里所解释的那番)。 + +## 成长期 + +后来,我切换到 DocBook XML 并使用 Kate 写作,但我发现它太繁琐了。因此,我迁移到 OpenOffice,它具有非常好的控制水准,并且提供了格式化与 PDF 生成功能,但是它从文档生成的 HTML 太过潦草。 + +最后,我发现了 XEmacs,我(再一次)采用 DocBook XML 重写了原先那一潦草的版本,并将这一格式作为长期的解决方案。 + +到了第六版时,我决定使用 Quanta+ 来处理所有的编辑工作,并使用 Fedora Core 3 Linux 提供的标准 XSL 样式表。不过,我通过编写 CSS 文档来为 HTML 页面提供颜色与样式设定。我同时还编写了一个粗糙的词法分析器,当然,用 Python 编写, 它能够自动为所列出的所有程序提供语法高亮。 + +等到第七版时,我使用 [MediaWiki](http://www.mediawiki.org) 作为我配置的基础。我使用它在线编辑几乎一切内容并允许读者在 Wiki 网站中直接阅读、编辑、讨论,但是最终我耗费了比写作还要多的时间在打击垃圾评论上。 + +第八版时我使用 [Vim]({{ book.vimBookUrl }}),[Pandoc](http://johnmacfarlane.net/pandoc/README.html) 和 Mac OS X 来写作。 + +第九版时我切换至 [AsciiDoc 文档格式](http://asciidoctor.org/docs/what-is-asciidoc/) 并使用 [Emacs 24.3](http://www.masteringemacs.org/articles/2013/03/11/whats-new-emacs-24-3/), [tomorrow 主题](https://github.com/chriskempson/tomorrow-theme), [Fira Mono 字体](https://www.mozilla.org/en-US/styleguide/products/firefox-os/typeface/#download-primary) 和 [adoc-mode](https://github.com/sensorflo/adoc-mode/wiki) 来写作。 + +## 现在 + +2016 年:我已厌倦去处理 AsciiDoctor 中的几个小的渲染问题,例如 `C/C++` 中的 `++` 会突然消失,这个问题如其它一些小问题一样很难追踪。再加上,因为 Asciidoc 的复杂格式,我已经不愿意再编辑文本。 + +因此在第十版中,我切换至 Markdown 和 [GitBook](https://www.gitbook.com),并使用它们的格式,通过 [Spacemacs editor](http://spacemacs.org) 来写作。 + +## 关于作者 + +请参阅 {{ book.authorUrl }} 。 diff --git a/22.revision_history.md b/22.revision_history.md new file mode 100644 index 00000000..d178777a --- /dev/null +++ b/22.revision_history.md @@ -0,0 +1,100 @@ +# 附录:本书由来 {#history-lesson} + +我第一次使用 Python 是因为我需要为我所编写的 “钻石(Diamond)”程序编写一个安装程序,这样我就能让安装过程更加便捷。我必须要在 Qt 库的 Python 与 Perl 的绑定间做出选择。我在网上了做了些研究,然后我便发现了[埃里克·雷蒙(Eric S. Raymond)撰写的一篇文章](http://www.python.org/about/success/esr/),埃里克是一名著名且备受尊重的黑客,在文章中他说 Python 已经成为了他最喜欢的编程语言。同时我也发现相比起 Perl-Qt 绑定, PyQt 绑定更加成熟。于是,我决定 Python 将成为我要使用的语言。 + +然后,我便开始搜寻针对 Python 的好书。但是我找不到!我找到了一些 O'Reilly 的书,但它们都十分昂贵,而且比起教材更像是一本参考手册。于是我通过 Python 官方文档来解决了学习的问题。不过它们都太简略短小。它确实提供了有关 Python 的优秀观念与视角,但还不够完整。我能够驾驭它是因为我已经有了编程经验,但对于新手来说这就完全不适合了。 + +在我与 Python 第一次接触的六个月后,我安装了(在当时)最新的 Red Hat 9.0 Linux,并开始使用 KWord。我对这款软件兴奋不已,突然变有了写一些有关 Python 的东西的想法。最开始我只写了几页但很快它便变成了 30 页长的文章。在这时,我开始认真考虑将其演变成更为有用的图书形式。在历经了相当_多_的重写之后,它终于成为一份有所用处的 Python 语言学习指南。我开始考虑将这本书作为我对开源社区的贡献与致敬。 + +这本书最初是作为我个人的 Python 笔记而存在,在未来我想还会依旧如此,尽管我已经对其作出了许多努力让它在他人面前能够显得更为可口。:) + +因为有着真正的开源精神,我收到了来自热心读者的许多建设性建议、批评与[反馈](./README.md#who-reads-bop),这些在我改进这本书的过程中对我帮助颇深。 + +## 本书目前的状态 + +本书需要来自它的读者帮助,例如由你来指出这本书的任何部分还不够好,难以理解或整个就是错的。请[写信给主要作者]({{ book.contactUrl }}) 或者向相应的[译者](./23.translations.md#translations)提交你的意见和建议。 + +# 附录:修订历史 {#revision-history} + +- 4.0 + - 2016 年 1 月 19 日 + - 切换回 Python 3。 + - 切换至 Markdown,采用 [GitBook](https://www.gitbook.com) 与 [Spacemacs](http://spacemacs.org)。 +- 3.0 + - 2014 年 3 月 31 日 + - 为 Python 2 进行重写,采用 [AsciiDoc](http://asciidoctor.org/docs/what-is-asciidoc/) 与 [adoc-mode](https://github.com/sensorflo/adoc-mode/wiki)。 + +- 2.0 + - 2012 年 10 月 20 日 + - 在 [Pandoc 格式](http://johnmacfarlane.net/pandoc/README.html)下重写,感谢我的妻子,是她完成了大部分从 MediaWiki 格式转换文本的工作。 + - 简化文本,删除不必要的部分,诸如 `nonlocal` 与元类。 + +- 1.90 + - 2008 年 9 月 4 日,目前仍在推进中 + - 在 3.5 年的止息后重新复兴! + - 为 Python 3.0 进行重写。 + - (再次)采用 [MediaWiki](http://www.mediawiki.org) 进行重写。 + +- 1.20 + - 2005 年 1 月 13 日 + - 在 [Fedora](http://fedoraproject.org/) Core 3 下使用 [Quanta+](https://en.wikipedia.org/wiki/Quanta_Plus) 全面重写。增添了诸多新的案例。重建了我的 DocBook 配置。 + +- 1.15 + - 2004 年 3 月 28 日 + - 零散修改。 + +- 1.12 + - 2004 年 3 月 16 日 + - 补充与修正。 + +- 1.10 + - 2004 年 3 月 9 日 + - 修正了更多的拼写错误,感谢这么多热心且大有帮助的读者。 + +- 1.00 + - 2004 年 3 月 8 日 + - 在读者提出了大量反馈与建议后,我对内容进行了重大修订,并订正了拼写错误。 + +- 0.99 + - 2004 年 2 月 22 日 + - 添加了有关模块的章节,增补了有关函数中的参数的变量数量的更多细节。 + +- 0.98 + - 2004 年 2 月 16 日 + - 编写了一个 Python 脚本与 CSS 样式表来改善 XHTML 输出,包括一个功能尚显粗糙的词法分析器,用以为列出的程序自动进行 VIM 式的加亮。 + +- 0.97 + - 2004 年 2 月 13 日 + - 又一版完全重写后的新版,(再次)采用 DocBook XML。本书已有大量改进——现在更加连贯且更加易读。 + +- 0.93 + - 2004 年 1 月 25 日 + - 增加了 IDLE 讨论与更多 Windows 相关的特定内容。 + +- 0.92 + - 2004 年 1 月 5 日 + - 修改了小部分案例。 + +- 0.91 + - 2003 年 12 月 30 日 + - 订正输入错误。对诸多话题进行改善。 + +- 0.90 + - 2003 年 12 月 18 日 + - 新增两篇章节。采用 [OpenOffice](https://en.wikipedia.org/wiki/OpenOffice) 格式并进行了修订。 + +- 0.60 + - 2003 年 11 月 21 日 + - 完全重写并扩充内容。 + +- 0.20 + - 2003 年 11 月 20 日 + - 订正某些输入错误并进行勘误。 + +- 0.15 + - 2003 年 11 月 20 日 + - 迁移至 [DocBook XML](https://en.wikipedia.org/wiki/DocBook) 与 XEmacs。 + +- 0.10 + - 2003 年 11 月 14 日 + - 使用 [KWord](https://en.wikipedia.org/wiki/Kword) 的首份草稿。 \ No newline at end of file diff --git a/23.translations.md b/23.translations.md new file mode 100644 index 00000000..f3a693cd --- /dev/null +++ b/23.translations.md @@ -0,0 +1,200 @@ +# 翻译 + +本书现在已经可以在多种不同的人类语言下阅读,感谢这些无私的志愿者们! + +如果你希望协助这些翻译工作,请先参阅下方的翻译语言与志愿者列表,再来决定是要帮助现有的翻译项目,还是重新开始翻译。 + +如果你计划开始一项新的翻译项目,请阅读[如何翻译本书](./24.translation_howto.md#translation-howto)。 + +## 阿拉伯语 + +下方提供了本书阿拉伯语版本的链接。感谢 Ashraf Ali Khalaf 翻译了本书,你可以在 在线阅读本书,也可以从 [sourceforge.net](http://downloads.sourceforge.net/omlx/byteofpython_arabic.pdf?use_mirror=osdn) 下载本书,想要了解关于本译本的更多信息,可以访问 。 + +## 阿塞拜疆语 + +Jahangir Shabiyev (c.shabiev@gmail.com) 志愿将本书翻译成阿塞拜疆语。目前翻译项目正在 https://www.gitbook.com/book/jahangir-sh/piton-sancmasi 推进中。 + +## 巴西葡萄牙语 + +本书现在有两版巴西葡萄牙语译本,它们的翻译进度与可阅览与否各有不同。老译本现已散佚遗失,新译本目前尚未完成。 + + +Samuel Dias Neto (samuel.arataca@gmail.com) 翻译了本书的第一版巴西葡萄牙语译本(老译本),当时 Python 还停留在 2.3.5 版。现在已找不到本译本的任何公开版本。 + +[Rodrigo Amaral](http://rodrigoamaral.net) (rodrigoamaral@gmail.com) 志愿将本书翻译至巴西葡萄牙语(新译本),目前本译本还未完成。 + +## 加泰罗尼亚语 + +Moises Gomez (moisesgomezgiron@gmail.com) 志愿将本书翻译至加泰罗尼亚语。目前翻译仍在进行中。 + +> Moisès Gómez - 我是一名开发者,同时也是一名编程教师(通常为没有任何编程经验的普通人教学) +> +> 一段时间之前我需要学习如何使用 Python 编程,Swaroop 的作品真的非常有帮助。简洁明了,足够完整。正是我所需要的。 +> +> 有了这次经历之后,我想到在我的国家还有些其他人也可以从中有所收获,但英语可能会是一个障碍。 +> +> 所以,为什么不试着把它翻译了呢?于是我便翻译了先前版本的 BoP。 +> +> 在我的国家有着两种官方语言,我选择加泰罗尼亚语,因为我想着会有人把它翻译成使用更为广泛的西班牙语。 + +## 中文 + +2005 年,沈洁元将本书 1.20 版翻译成简体中文,并发布到互联网上。在 BoP 官方网站上,他留名为 Juan Shen,邮箱地址为 orion_val@163.com。这一译本在互联网上广为流传,以至于其最初的出处已不可考,原先提供在 BoP 官网上的链接也已经失效,因此此处无法给出一个确切的下载链接。你可以通过搜索“简明Python教程 沈洁元”或类似关键词来获得一份副本。 + +2017 年,漠伦(i@molun.net)基于原书 4.0 版重新翻译出了新译本,并托管于 GitHub 与 Gitbook。他还在持续跟进这一译本,并不断修正译本中可能存在的任何错误与疏漏。 + +2017 版译本可以在 https://bop.molun.net 上浏览并获得。 + +## 繁体中文 + +Fred Lin (gasolin@gmail.com) 志愿将本书翻译至繁体中文。 + +你可以在 找到这本书。 + +这一译本的一大令人激动之处在于其包含了_可执行的中文 Python 源代码_ ,同时还包括了 Python 的原始源代码。 + +> Fred Lin - 我是一名供职于 Delta Network 网络硬件工程师,同时我还是一名 TurboGears 网络框架的贡献者。 +> +> 作为一位 Python 福音传道者(:-p),我需要一些素材来推广 Python 语言。我发现《简明 Python 教程》无论是对于新手还是有经验的程序员都是一道绝佳甜点。《简明 Python 教程》用一个可承受的篇幅讲解了 Python 中的要点所在。 +> +> 这一译本最开始基于简体中文译本,尔后很快就历经了大量重写以适应现在的维基版本以及阅读质量。 +> +> 现在的繁体中文版本还包括了一套可执行的中文 Python 源码,它收录在我的我的新项目“zhpy”(Python in Chinese)中(自 8 月 7 日起运行)。 +> +> zhpy(读作Z.H.? 或者读作 zippy)在 Python 之上建立了新的一层用以将 Python 翻译至中文或使用中文交互(无论是简体还是繁体)。该项目主要目标是用于教育用途。 + +## 法语 + +Gregory (coulix@ozforces.com.au) 志愿将本书翻译至法语。 + +Gérard Labadie (gerard.labadie@gmail.com) 完成了将本书翻译至法语的工作。 + +## 德语 + +Lutz Horn (lutz.horn@gmx.de), Bernd Hengelein (bernd.hengelein@gmail.com) 与 Christoph Zwerschke (cito@online.de) 共同志愿将本书翻译至德语。 + +他们的译本现在存储在 。 + +Lutz Horn 说: + +> 我今年 32 岁,在德国海德尔堡大学获得了数学学位。目前我正作为一名软件工程师供职于一个公共资助项目,为德国所有与计算机科学相关的事物建立一家门户网站。当下我所使用的主要语言是 Java,但我希望在后台能尽可能多地使用 Python。特别是文本分析与转换这类工作能够很容易用 Python 处理。我并不是很熟悉 GUI 工具包,因为我大部分的编程工作都是与 Web 应用有关,这些工作的用户界面大都是由诸如 Struts 这些 Java 框架构建的。现在我正尝试尽可能多地利用 Python 和它的生成器的功能性编程特性。在短暂接触过 Ruby 之后,我对这一语言对块的使用方式有着深刻印象。 总的来说,我喜欢 Python 和 Ruby 这些语言的动态特性,因为它允许我做更多的事情,而是在其他更多如 Java 这些静态语言中所不能做到的。我搜索了一些有关编程的介绍,特别是那些适合向完全没有编程经验的人传授的内容。我曾经找到了名为《How to Think Like a Computer Scientist: Learning with Python》《Dive into Python》的教材,前者足够优秀但对于翻译工作而言太长了,后者则不太适合新手。我认为《简明 Python 教程》在两者间取得了很好的平衡,因为它既不长,同时在传授给新手时也足够详细。除开这些,我喜欢 DocBook 的简单结构,这种结构能够通过多种丰富格式为翻译文本提供富有吸引力的输出生成。 + +Bernd Hengelein 说: + +> Lutz 与我正准备一同进行德语翻译工作。我们刚刚开始翻译介绍与序言部分,但我们会让你知道我们所推进的任何进展。好的,接下来是一些有关于我个人的事情。我今年已 34 岁,自 1980 年代以来我与电脑共舞的的时间已经超过 20 年了,当时“Commodore 64”正统治着托儿所。在学习了计算机科学后我开始以软件工程师的身份参与工作。现在我在一家德国大型公司的医疗成像领域工作。尽管 C++ 是我主要的编程语言,同时我也(必须)使用它展开每天的工作,我仍在不断寻找新的东西来学习。就在去年我爱上了 Python,无论是它的可能性还是它的美丽皆令人惊叹不已。我曾在网上某处看到一个人说他喜欢 Python 是因为它的代码看起来是如此漂亮。在我看来,他所说的确是如此。自那时起我便决定要学习 Python,而我发现只有非常少的优秀文档能在德语之下阅读。当我偶然遇到你的这本书时,要将它翻译成德语的想法自然而然地横亘在我的心间。幸运的是,Lutz 与我有着相同的想法,于是现在我们可以分工而动。我期待着我和 Lutz 能有一个良好的合作! + +## 希腊语 + +Ubuntu 希腊社区 [将本书翻译至希腊语](http://wiki.ubuntu-gr.org/byte-of-python-el),这一译本用于我们在社区中举办的在线异步 Python 课程。联系 [@savvasradevic](https://twitter.com/savvasradevic) 以获取更多信息。 + +## 印度尼西亚语 + +Daniel (daniel.mirror@gmail.com) 正在 上将本书翻译至印度尼西亚语。 + +Wisnu Priyambodo (cibermen@gmail.com) 同样志愿将本书翻译至印度尼西亚语。 + +同时,Bagus Aji Santoso (baguzzzaji@gmail.com) 也志愿参与其中。 + +## 意大利语(第一版) + +Enrico Morelli (mr.mlucci@gmail.com) 与 Massimo Lucci (morelli@cerm.unifi.it) 志愿将本书翻译至意大利语。 + +该意大利语译本现在存放在 。 + +> _Massimo Lucci and Enrico Morelli_ - 我们就职于佛罗伦萨大学(意大利)的化学系。我(Massimo)担任核磁共振光谱仪的服务工程师与系统管理员;Enrico 在我们的 CED 与并行/集群系统中担任服务工程师与系统管理员。我们使用 Python 编程已经有七年了,在 Linux 平台上工作的时间亦有十年之久。在意大利,我们负责并管理与 Gentoo/Linux 有关的 www.gentoo.it 网站,同时我们还是为核磁共振应用程序与大会组织和管理提供服务的 www.nmr.it 网站的贡献者(网站目前正在建设)。与我们有关的就是这些!我们对你这本书中所使用的只能语言印象深刻,并认为推荐 Python 给新的使用者(我们正考虑向我们实验室中数百位学生与研究者推荐)是极具必要的。 + +## 意大利语(第二版) + +另一份意大利语译本由 [Calvina Bice](http://besthcgdropswebsite.com/translate) 与其同事于 翻译。 + +## 日语 + +Shunro Dozono (dozono@gmail.com) 正在将本书翻译至日语。 + +## 韩语 + +Jeongbin Park (pjb7687@gmail.com) 志愿将本书翻译至韩语: + +> 我是 Jeongbin Park,现在是韩国的一名生物物理与生物信息学研究员。 +> +> 一年前,我曾寻找一本足够好的 Python 教程来推荐给我的同事,因为在我们这一研究领域中使用 Python 已经越来越不可避免,它的用户基数正不断增长。 +> +> 但是在那时只有很少的 Python 图书拥有韩语版本,所以我决定翻译你撰写的这本电子书,因为它是我度过的最好的一本 Python 指南! +> +> 现在,这本书的大部分都已翻译到韩语,还剩下介绍章节和附录中的一些内容。 +> +> 再次感谢你编写出了这本如此优秀的指南! + +## 蒙古语 + +Ariunsanaa Tunjin (luftballons2010@gmail.com) 志愿将本书翻译至蒙古语。 + +2009 年 11 月 9 日更新:Ariunsanaa 现在已几乎完成翻译工作。 + +## 挪威语(巴克摩挪威语) + +Eirik Vågeskar 是一名在挪威 [Sandvika videregående skole](http://no.wikipedia.org/wiki/Sandvika_videreg%C3%A5ende_skole) 就读的一名高中生,目前他正在将本书翻译至挪威语(巴克摩挪威语)。 + +> _Eirik Vågeskar_: 我一直都想学习编程,但是因为我的母语属于小语种,使得这一学习过程变得十分困难。大部分教程与教材书都采用非常专业的英语来撰写,所以大部分高中毕业生都不会有相应的词汇量来理解教程说的究竟是什么。当我发现这本书时,我的所有问题都被解决了。《简明 Python 教程》用着简单而非专业性的语言来解释一种同样简单的程序语言,这二者使得学习 Python 成了一项趣事。在阅读了这本书的一半篇幅时候,我认为这本书是值得去翻译。我希望翻译出来的一本能够帮助与我出于相同境地的人(尤其是年轻人),也或许能够有利于在那些只具有少数技术知识的人之间传递对这一编程语言的兴趣。 + +## 波兰语 + +Dominik Kozaczko (dominik@kozaczko.info) 志愿将本书翻译至波兰语。该译本的翻译工作目前正在进行,它的主页设置在此:[Ukąś Pythona](http://python.edu.pl/byteofpython/)。 + +更新:现在本译本已翻译完成并于 2009 年 10 月 2 日准备就绪。感谢 Dominik、他的两位学生和他们的朋友,感谢他们所奉献出的时间与精力! + +> _Dominik Kozaczko_ - 我是一名计算机科学与信息技术教师。 + +## 葡萄牙语 + +Fidel Viegas (fidel.viegas@gmail.com) 志愿将本书翻译至葡萄牙语。 + +## 罗马尼亚语 + +Paul-Sebastian Manole (brokenthorn@gmail.com) 志愿将本书翻译至罗马尼亚语。 + +> _Paul-Sebastian Manole_ - 我是一名就读于罗马尼亚 Spiru Haret 大学的计算机科学二年级学生。我是一名自学程序员并正准备去学习一门新的语言——Python。网络上的信息告诉我没有别的方式比阅读《简明 Python 教程》会更好了。你便可以料想这本书究竟有多流行(祝贺作者能够编写出这本这么容易就能读懂的书)。我开始喜欢上 Python,因此我决定协助将 Swaroop 的书的最新版本翻译至罗马尼亚语。尽管我是第一个发起倡议的人,但我也不过是一名志愿者,如果你有意提供帮助,请加入我。 + +## 俄语 + +Vladimir Smolyar (v_2e@ukr.net) 在 完成了本书的俄语翻译。 + +## 乌克兰语 + +Averkiev Andrey (averkiyev@ukr.net) 志愿将本书翻译至俄语,可能还有乌克兰语(如果时间允许的话)。 + +## 塞尔维亚语 + +"BugSpice" (amortizerka@gmail.com) 已完成了本书的塞尔维亚语译本: + +> 此下载链接已不再可用。 + +有关更多细节可以访问:。 + +## 斯洛伐克语 + +Albertio Ward (albertioward@gmail.com) 将本书翻译至斯洛伐克语:。 + +> 我们是非盈利组织“教育翻译(Translation for education)”。我们现在有着一群成员,主要是来自 Slavonic 大学的学生与教授。这里有来自不同院系的学生:语言学、化学、生物学等等。我们试图在互联网上发现有趣且可能与我们以及我们的同事有关的的出版物。有时我们会自己去发现文章;其他时候我们的教授会帮助我们选择用以翻译的材料。在获得了作者的许可之后,我们会翻译这些文章并将其张贴于我们的博客之上,供我们的同事于朋友浏览。这些翻译后的出版物经常为我们的学生的日常学习生活提供帮助。 + +## 西班牙语 + +Alfonso de la Guarda Reyes (alfonsodg@ictechperu.net), Gustavo Echeverria (gustavo.echeverria@gmail.com), David Crespo Arroyo (davidcrespoarroyo@hotmail.com) 还有 Cristian Bermudez Serna (crisbermud@hotmail.com) 志愿将本书翻译至西班牙语。 + +Gustavo Echeverria 说: + +> 我在阿根廷担任软件工程师的工作。在工作中我通常使用 C# 与 .Net 技术,但在我的个人项目中,我坚守着使用 Python 和 Ruby。我在很多年前了解到 Python 并且很快便爱上了它。在我接触 Python 没多久后我便发现了这本书,是它帮助我学习这门语言。然后我便志愿将这本书翻译至西班牙语。在接到了数个请求之后,现在我开始在 Maximiliano Soler 的帮助下翻译《A Byte of Python》。 + +Cristian Bermudez Serna 说: + +> 我是哥伦毕业安蒂奥基亚大学的电信工程专业的学生。几个月前,我开始学习 Python 编程并发现了这本美妙的教材,所以我决定志愿加入西班牙语翻译。 + +## 瑞典语 + +Mikael Jacobsson (leochingkwake@gmail.com) 志愿将本书翻译至瑞典语。 + +## 土耳其语 + +Türker SEZER (tsezer@btturk.net) 与 Bugra Cakir (bugracakir@gmail.com) 志愿将本书翻译至土耳其语。 + +"Where is Turkish version? Bitse de okusak." \ No newline at end of file diff --git a/24.Translation-how-to.md b/24.Translation-how-to.md new file mode 100644 index 00000000..d23df8db --- /dev/null +++ b/24.Translation-how-to.md @@ -0,0 +1,8 @@ +# 如何翻译本书 {#translation-howto} + +1. 本书的完整源代码可在 {{ book.sourceUrl }} 获得。 +2. 请 [Fork 整个库](https://help.github.com/articles/fork-a-repo)。 +3. 然后,将库提取至你的电脑上。你需要了解如何通过 [Git](http://www.git-scm.com) 来实现这一过程。 +4. 阅读 [GitBook 文档](https://help.gitbook.com) ,尤其是 [Markdown 章节](https://help.gitbook.com/format/markdown.html)。 +5. 开始编辑 `.md` 文件,将其翻译至你的本地语言。 +6. [在 GitBook.com 上注册帐号](https://www.gitbook.com),创建一本书籍,然后你便可以呈现出的精美网站,还包括 PDF、EPUB 等格式的下载链接。 \ No newline at end of file diff --git a/25.Feedback.md b/25.Feedback.md new file mode 100644 index 00000000..b8f7a41b --- /dev/null +++ b/25.Feedback.md @@ -0,0 +1,10 @@ +# 反馈 + +本书需要来自它的读者帮助,例如由你来指出这本书的任何部分还不够好,难以理解或整个就是错的。请 [写信给作者]({{ book.contactUrl }}) 提交你的意见和建议。 + +有关本中文译本,如果你认为书中的某些部分的翻译存在疏漏或错译、误译,又或者你觉得有更好的表述,你可以[写信给译者](mailto:i@molun.net)提交你的意见或建议。 + +在向译者提供反馈时,请提供以下信息: + +- 参考译本版本号,在全书开头可以查看到。 +- 与反馈内容相关的章节位置,如“《面向对象编程》的‘类’一节”。由于译者在修订时是直接在源文件上修改,提供 PDF/EPUB 的页数不便于查找,还请理解。 diff --git a/INSTALL.md b/INSTALL.md deleted file mode 100644 index 92c266d8..00000000 --- a/INSTALL.md +++ /dev/null @@ -1,6 +0,0 @@ -``` -npm install -g gitbook-cli -gitbook serve -``` - -See http://toolchain.gitbook.com/ebook.html diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..2e72ca11 --- /dev/null +++ b/LICENSE @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/README.md b/README.md index 0a12e09a..bcf65ff7 100644 --- a/README.md +++ b/README.md @@ -1,283 +1,161 @@ -# A Byte of Python +# 介绍 -"A Byte of Python" is a free book on programming using the Python language. It serves as a tutorial or guide to the Python language for a beginner audience. If all you know about computers is how to save text files, then this is the book for you. +《A Byte of Python》是一本由 **Swaroop C H** 编写,旨在于介绍如何使用 Python 语言进行编程的自由图书。它以教材与指南的形式为入门者介绍 Python 语言。如果你对电脑知识的了解仅限于如何保存文本文件的话,那这本书就是为你准备的。 -## For Python version 3 +2005 年,**沈洁元**将本书的 1.20 版引进中国,并完成了全本翻译,将本书的译名定为《简明 Python 教程》。2017年,**漠伦**基于原书 4.0 版重新翻译,制作了本版全新译本,并沿用同样的译名。 -This book will teach you to use Python version 3. There will also be guidance for you to adapt to the older and more common Python version 2 in the book. +本版译本定义为 4.08c 版。最后修订于 2018 年 2 月 4 日。 -## Who reads A Byte of Python? {#who-reads-bop} +## 有关 Python 3 -Here are what people are saying about the book: +本书将指导你如何使用 Python 3。同时,本书也会以指南的形式告诉你应如何适应虽老些但使用更加普遍的 Python 2。 -> This is the best beginner's tutorial I've ever seen! Thank you for your effort. -> -- [Walt Michalik](mailto:wmich50@theramp.net) +## 都有谁阅读了本书? - +下面是一些人对本书的评价: -> The best thing i found was "A Byte of Python", which is simply a brilliant book for a beginner. It's well written, the concepts are well explained with self evident examples. -> -- [Joshua Robin](mailto:joshrob@poczta.onet.pl) +> 这本书是我所见过的最好的新手教程!感谢你所做的努力。 ——[Walt Michalik](mailto:wmich50@theramp.net) - +> 我所遇见的最好的事就是发现了《简明 Python 教程》,它确实是一本为新手准备的绝佳书籍。它撰写出色,清楚解释了诸多定义,并都配以了清晰的案例。 -- [Joshua Robin](mailto:joshrob@poczta.onet.pl) -> Excellent gentle introduction to programming #Python for beginners -> -- [Shan Rajasekaran](https://twitter.com/ShanRajasekaran/status/268910645842423809) +> 一份面向新手的出色而温和的 #Python 编程指南。 -- [Shan Rajasekaran](https://twitter.com/ShanRajasekaran/status/268910645842423809) - +> 最佳 Python 新手指南 -- [Nickson Kaigi](https://twitter.com/nickaigi/status/175508815729541120) -> Best newbie guide to python -> -- [Nickson Kaigi](https://twitter.com/nickaigi/status/175508815729541120) +> 在每一页的阅读中开始爱上 Python。 -- [Herbert Feutl](https://twitter.com/HerbertFeutl/status/11901471389913088) - +> Python 的最佳新手教程,它将会给你一把打开 Python 奇幻世界的钥匙。 -- [Dilip](https://twitter.com/Dili\_mathilakam/status/220033783066411008) -> start to love python with every single page read -> -- [Herbert Feutl](https://twitter.com/HerbertFeutl/status/11901471389913088) +> 我本应开始我实际的“工作”,但我却恰巧发现了这本《简明 Python 教程》。一本附有优秀例子的杰出教材。 -- [Biologist John](https://twitter.com/BiologistJohn/statuses/194726001803132928) - +> 最近我开始阅读《简明 Python 教程》。一部优秀的作品。而且它是免费的。强烈推荐给那些具有抱负的 Pythonistas(译注:热衷使用 Python 语言编程的人)。 -- [Mangesh](https://twitter.com/mangeshnanoti/status/225680668867321857) -> perfect beginners guide for python, will give u key to unlock magical world of python -> -- [Dilip](https://twitter.com/Dili_mathilakam/status/220033783066411008) +> 《简明 Python 教程》,由 Swaroop 撰写(我目前在读的书)。可能是最适合用以入门,也可能世界上最好的面向每一位新手甚至是有经验的用户的教材。 -- [Apostolos](http://apas.gr/2010/04/27/learning-python/) - +> 阅读 @swaroopch 所撰写的最好的一本书 #ByteOfPython 确是享受。 -- [Yuvraj Sharma](https://twitter.com/YuvrajPoudyal/status/448050415356346368) -> I should be doing my actual "work" but just found "A Byte of Python". A great guide with great examples. -> -- [Biologist John](https://twitter.com/BiologistJohn/statuses/194726001803132928) +> 十分感谢你撰写了《简明 Python 教程》。我两天前才刚刚开始学习如何编写代码,现在我已经完成了两款简单游戏的编写。你编写的教程十分完美,我在此就是想让你知道它是多么富有价值。 -- Franklin - +> 我是一名来自 Dayanandasagar 大学的工程学(第七期,CSE)学生。首先,我想说你的《简明 Python 教程》这本书非常适合像我这样的 Python 新手。被出色解释清楚的概念以及简单的例子帮助我更加容易地学习 Python。十分感谢你。 -- Madhura -> Recently started reading a Byte of python. Awesome work. And that too for free. Highly recommended for aspiring pythonistas. -> -- [Mangesh](https://twitter.com/mangeshnanoti/status/225680668867321857) +> 我是一名 18 岁学生,现在在爱尔兰的大学学习信息技术。我希望能在此表达我的感激之情:感谢你写出了《简明 Python 教程》。此前我已经具备了 3 门编程语言的知识——C,Java,还有 Javascript。而 Python 是我所接触并学习过的编程语言里最简单的一门,这全都要归功于你的这本书,它是如此优秀,将学习 Python 的历程变得如此简单而有趣。这是我所读过的有关编程的书籍里最优秀的一本。祝贺你所完成的这项伟大工作,并希望你能将它继续下去。 -- Matt - +> 嗨,我来自多米尼加共和国,我的名字是 Pavel。最近我读了你的 _《简明 Python 教程》_,发现它是如此精彩!:)我从这些范例中学到了很多。你的这本书对像我这般的新手提供了很大的帮助。 -- [Pavel Simo](mailto:pavel.simo@gmail.com) -> A Byte of Python, written by Swaroop. (this is the book I'm currently reading). Probably the best to start with, and probably the best in the world for every newbie or even a more experienced user. -> -- [Apostolos](http://apas.gr/2010/04/27/learning-python/) +> 我是一名来自中国的学生。现在,我读了你的《简明 Python 教程》这本书,不由感叹它实在是太美妙了。这本书是如此简明扼要但却能帮助所有第一次学习编程的人。你知道,我对 Java 抱有兴趣,并且运行过很多次云计算。我曾为服务器编写程序,所以我觉得 Python 会是一个好选择。在阅读完你的这本书后,我觉得这不仅仅只是一个好选择,而是我必须、理应使用 Python。我的英语算不上很好,寄这一封邮件只是想向你诉说一声“谢谢”!为你与你的家人致以我最好的祝福。 -- Roy Lau - +> 我最近刚刚完成了对《简明 Python 教程》的阅读,我觉得我实在应当感谢你。在阅读到最后一页后,我对自己将要重归于其它沉闷、枯燥、乏味的 Python 教程与指南中而伤心不已。无论如何,我真的很感谢你的这本书。 -- [Samuel Young](mailto:sy137@gmail.com) -> Enjoying Reading #ByteOfPython by @swaroopch best book ever -> -- [Yuvraj Sharma](https://twitter.com/YuvrajPoudyal/status/448050415356346368) +> 亲爱的 Swaroop,我正上着一门对教学了无兴趣的教师所教授的课程。我们正在使用由 O'Reilly 出品的《Python 学习手册(Learning Python)》第二版。它并非面向没有任何编程知识的初学者的教材,而一名教师应该在另一种领域来进行教学。非常感谢你的这本书,如果没有它那我在 Python 和编程面前只能碌碌无为。真的是万分感谢,你能够\_打破这信息的壁垒\_使得每一个初学者都可以理解这些内容,这并非每个人都能做到的事情。 -- [Joseph Duarte](mailto:jduarte1@cfl.rr.com) - +> 我真是喜欢你的这本书!它真的是最好最好的 Python 教程,同时也是非常有用的参考。令人赞叹,真正的杰作!愿你能够继续这项伟大的工作! -- Chris-André Sommerseth -> Thank you so much for writing A Byte Of Python. I just started learning how to code two days ago and I'm already building some simple games. Your guide has been a dream and I just wanted to let you know how valuable it has been. -> -- Franklin +> 首先,我希望能够向你表达我对这本优秀的书的感谢。我认为这是一本对于那些正在寻找优秀的 Python 初学者教程的人的最佳教材。 我想可能是在两三年前,当我第一次听说这本书时,那时的我尚不能阅读英语撰写的书籍,所以我找到了一本中文译本,是那本中文译本将我带进了 Python 编程世界的大门。 最近,我重新读了这本书。当然,这一次我读的是英语版本的。我简直不敢相信我可以不借助手边的字典就读完这本书。自然,它全应归功于你的工作,是你让这本书变得如此易于理解。 -- [myd7349](https://github.com/swaroopch/byte\_of\_python/pull/13) - +> 我在此通过邮件对你在网络上撰写的《简明 Python 教程》向你表达感谢。在遇到你的这本书之前,我曾花费数月的时间来尝试使用 Python,尽管我通过 pyGame 获得了些许收获,但我还尚未完成一款程序。 感谢你简化了个中类别,使得学习 Python 真的变成了看起来能够达到的目标。现在看来我已经学会了 Python 的基础,并且能够继续下去,实现我的目标——游戏开发。 …… 再一次感谢你在网络上提供这本结构化、对基础编程很有帮助的教程。它助我对 OOP(面向对象编程)内外都有了足够的理解,这是过去我所学习的两本教材都没能做到的事情。 -- [Matt Gallivan](mailto:m\_gallivan12@hotmail.com) -> I'm from Dayanandasagar College of Engineering (7th sem, CSE). Firstly i want to say that your book "The byte of python" is too good a book for a beginner in python like me.The concepts are so well explained with simple examples that helped me to easily learn python. Thank you so much. -> -- Madhura +> 我要感谢你和你的书 _《简明 Python 教程》_,它是我所能找到的最好的编程学习方式。我的名字叫 Ahmed,15岁,来自埃及。Python 是我学习的第二门编程语言。我曾在学校学习了 Visual Basic 6,但并不是很喜欢它,但现在我十分享受学习 Python 的过程。我编写了一款通讯录程序并且取得了成功。我将开始尝试编写更多程序,也试着去阅读 Python 程序(如果你能告诉我它们的源代码,那会对我大有帮助)。我现在也开始学习 Java,如果你能够告诉我哪里能找到如你的这本书这般优秀的 Java 教程,那真的是帮到我大忙了。感谢你。 -- [Ahmed Mohammed](mailto:sedo\_91@hotmail.com) - +> 由 Swaroop C H 撰写的《简明 Python 教程》这本 110 页的 PDF 教程是针对想要更多地了解 Python 的初学者的绝佳资源。它精心编写,易于跟随,同时还可能是针对 Python 编程的最佳介绍。 -- [Drew Ames](http://www.linux.com/feature/126522) -> I am a 18 year old IT student studying at University in Ireland. I would like to express my gratitude to you for writing your book "A Byte of Python", I already had knowledge of 3 programming langagues - C, Java and Javascript, and Python was by far the easiest langague I have ever learned, and that was mainly because your book was fantastic and made learning python very simple and interesting. It is one of the best written and easy to follow programming books I have ever read. Congratulations and keep up the great work. -> -- Matt +> 昨天我在我的诺基亚 N800 上阅读了《简明 Python 教程》的大部分内容,这是我所遇到过的最简单也最简洁的 Python 介绍。强烈推荐以这本书作为你学习 Python 的起点。 -- [Jason Delport](http://paxmodept.com/telesto/blogitem.htm?id=627) - +> @swaroopch 撰写的《简明 Vim 教程(Byte of Vim)》与《简明 Python 教程》是我到目前所遇见的最好的技术写作作品。它们都是优秀的作品。#FeelGoodFactor -- [Surendran](http://twitter.com/suren/status/12840485454) -> Hi, I'm from Dominican Republic. My name is Pavel, recently I read your book _A Byte of Python_ and I consider it excellent!! :). I learnt much from all the examples. Your book is of great help for newbies like me... -> -- [Pavel Simo](mailto:pavel.simo@gmail.com) +> 《简明 Python 教程》是最好的。 (对问题“有人能推荐一本优秀且便宜的用来学习 Python 基础的资源吗?”的回答) -- [Justin LoveTrue](http://www.facebook.com/pythonlang/posts/406873916788) - +> 《简明 Python》十分有帮助……万分感谢。:) [Chinmay](https://twitter.com/a\_chinmay/status/258822633741762560) -> I am a student from China, Now ,I have read you book A byte of Python, Oh it's beautiful. The book is very simple but can help all the first learnners. You know I am interesting in Java and cloud computing many times, i have to coding programm for the server, so i think python is a good choice, finish your book, i think its not only a good choice its must use the Python. My English is not very well, the email to you, i just wanna thank you! Best Wishes for you and your family. -> -- Roy Lau +> 一直以来都是《简明 Python 教程》的粉丝——它同时为新程序员与有经验的程序员所编写。 -- [Patrick Harrington](http://stackoverflow.com/a/457785/4869) - +> 从几天前我开始从你的书中学习 Python……感谢这本优秀的书。它撰写的如此优秀,使我的学习生活 更加容易……现在你有了一名新粉丝——那就是我。:)万分感谢。 -- [Gadadhari Bheem](https://twitter.com/Pagal\_e\_azam/statuses/242865885256232960) -> I recently finished reading Byte of Python, and I thought I really ought to thank you. I was very sad to reach the final pages as I now have to go back to dull, tedious oreilly or etc. manuals for learning about python. Anyway, I really appreciate your book. -> [Samuel Young](mailto:sy137@gmail.com) +> 在我学习 Python 之前,我已经具有了 Assembly、C、C++、C# 和 Java 的基本编程能力。我想学习 Python 的原因是它十分流行(人们都在谈论它)且功能强大(现实如此)。这本由 Swaroop 先生所撰写的书是一本非常好的教材,它同时面向新程序员与新 Python 程序员。我花了 10 个半天来读完它,十分有帮助! -- [Fang Biyi (电气与计算机工程学博士候选人,密歇根州立大学)](mailto:fangbiyi@gmail.com) - +> 为这本书向你致谢!! 这本书消除了我在 Python 方面诸如面向对象编程等许多问题。 我不觉得我是 OO 方面的专家,但我知道这本书在我迈出的第一与第二步上帮助颇多。 我已经编写了几款 Python 程序,它们确实在我的系统管理员工作中帮我解决了诸多事情。它们都是程序性的,但是在许多人的标准看来它们都如此小巧。 再次感谢这本书。感谢你将它公开在网络上。 -- Bob -> Dear Swaroop, I am taking a class from an instructor that has no interest in teaching. We are using Learning Python, second edition, by O'Reilly. It is not a text for beginner without any programming knowledge, and an instructor that should be working in another field. Thank you very much for your book, without it I would be clueless about Python and programming. Thanks a million, you are able to _break the message down_ to a level that beginners can understand and not everyone can. -> -- [Joseph Duarte](mailto:jduarte1@cfl.rr.com) +> 我希望为你撰写的这本我所阅读过的最佳编程书籍向你表示感谢。Python 并不是我使用的第一门语言,但我可以想象它可以拥有的一切可能性。十分感谢你予我这个工具,让我可以创造那些我从未想过我能创造的一切。 -- "The Walrus" - +> 我希望为你所撰写的 _《简明 Python 教程》(第 2 版与第 3 版)_ 向你表示感谢。它在我整个学习 Python 与编程的历程中弥足珍贵。 不必多言,我是编程世界里的一名新手,我耗费了几个月的时间自己学习从而达到这样的程度。我曾通过 Yotube 教程和其它的一些诸如免费图书的在线教程来学习编程。就在昨天我决定深入学习你的这本书,现在我已经学了开头的几页,这比我在其他任何一本书或教程中所走过的进度都要多。有些事我曾一度感到困惑,但在这本书里这些**优秀**的解释和范例面前都得以解答。我已经等不及去阅读(学习)之后的更多内容了! 非常感谢你,不仅是撰写了这本书,还愿意把它通过知识共享协议授权分发(免费地)。感谢上帝,正是如此这样无私的人们帮助并教导了我们其余的这些人。 -- Chris -> I love your book! It is the greatest Python tutorial ever, and a very useful reference. Brilliant, a true masterpiece! Keep up the good work! -> -- Chris-André Sommerseth +> 在 2011 年时我曾向你写信,那时我才刚刚开始使用 Python,并想为你的教程《简明 Python 教程》向你表示感谢。如果没有它,我想我只会倒在路边。自那时起我已经在我的组织中使用 Python 这门语言编写程序,实现诸多功能,而在未来我相信我能写得更多。无论如何我也不会把自己称作一名高级程序员,但我发现自从我开始使用 Python 后,现在我时不时会收到来自他人的协助请求。我发现,在阅读《简》时,我已经放弃学习 C 和 C++,因为那些书里在一开始就向我抛出了一个包含增量赋值(Augmented Assignment)的例子。自然,没有任何为何有关在此安排这一赋值的解释,我只能用尽我的头脑去弄清楚纸上印出来的到底是什么内容。这是我所能记得的最令人沮丧的经历,最终我选择了放弃。这并不是意味着 C 或 C++ 是不可能学会的,抑或我是一个蠢蛋,但它的确意味着我工作中所拥有的文档不会包括任何有关符号或词语的定义,而这些确是在任何介绍中都至关重要的部分。正如计算机不能理解在其所使用的语言的语法之外的计算机词汇或计算机符号一般 ,任何一个领域的新学生如果遇到的全都是没有定义的符号与词汇,他就不能领会其主题所在。你会遇到某一情况下的“蓝屏”。其解决方案简单明了:找到个中词汇与符号并理解其正确的定义,如此一来——你瞧,计算机和学生都可以继续进行他们的任务。你的这本书将二者结合得如此之好,我在其中只有很少的部分无法掌握。因此,谢谢你。我鼓励您继续在书中囊括各术语的完整定义。一旦你有所了解,就能知道Python 的文档是优秀的(于我所见,范例就是它的力量)。但是在许多情况下,为了理解文档,你必须了解在我看来并不需要知道的东西。第三方教程都表示需要借助文档来澄清,它们的成功很大程度上都归功于那些用来描述术语的词语。我已经将你的这本书推荐给其他许多人。有的来自澳大利亚,有的在加勒比,还有一些在美国。它填补了其他人没能填补的位置。我希望你能继续这样好好做下去,并祝愿你在未来的所有成功。 -- Nick - +> 嗨,我是 Ankush(19岁)。我现在正在面对开始学习 Python 的巨大困难。我尝试了许多教材但它们都过于臃肿,而且也非目标导向;尔后我便遇到这可爱的一本,让我在短时间内就爱上了 Python。十分感谢这本“美妙的一本书”。 -- Ankush -> First of all, I want to say thanks to you for this greate book. I think it is a good book for those who are looking for a beginner's tutorial for Python. -> It is about two or there years ago, I think, when I first heard of this book. At that time, I am not able to read some book in English yet, so I got a chinese translation, which took me into the gate of Python programming. -> Recently, I reread this book. This time, of course, the english version. I couldn't believe that I can read the whole book without my dictionary at hand. Of course, it all dues to your effort to make this book an easy-to-understand one. -> -- [myd7349](https://github.com/swaroopch/byte_of_python/pull/13) +> 我要感谢你这本出色的 Python 指南。我是一位分子生物学家(仅有些许编程背景),在我的工作中我需要处理有关 DNA 序列的大数据集,还要分析显微镜图像。对于这些工作,采用 Python 编程对我十分有帮助,如果不是我必须要完成并发表一项历时六年的项目的话。 这样一本教程能够免费提供是邪恶尚未统治世界的确切标志!:) -- Luca - +> 既然这(Python)将是你学习的第一门编程语言,你应该采用《简明 Python 教程》。它确实为 Python 编程提供了恰当的介绍,且节奏十分适合一般初学者。在此之后最重要的事自然是切实地开始开始练习编写你自己的小程序。 -- ["{Unregistered}"](http://www.overclock.net/t/1177951/want-to-learn-programming-where-do-i-start#post\_15837176) -> I'm just e-mailing you to thank you for writing Byte of Python online. I had been attempting Python for a few months prior to stumbling across your book, and although I made limited success with pyGame, I never completed a program. -> Thanks to your simplification of the categories, Python actually seems a reachable goal. It seems like I have finally learned the foundations and I can continue into my real goal, game development. -> ... -> Once again, thanks VERY much for placing such a structured and helpful guide to basic programming on the web. It shoved me into and out of OOP with an understanding where two text books had failed. -> -- [Matt Gallivan](mailto:m_gallivan12@hotmail.com) +> 只是想满怀喜悦地大声说一声 _十分感谢你_,感谢你出版了《简明 Python 教程》和《简明 Vim 教程(A Byte of Vim)》。这两本书在我四五年前开始学习编程时对我大有帮助。现在我已经开始开发一项项目,一个开始于很久很久之前的梦想。我只是想对你说一声\_“谢谢你”\_。我将继续前进。你是我一大前进动力的来源。祝你一切顺利。 -- Jocimar - +> 在 3 天里我读完了《简明 Python 教程》。它真的非常有趣。书里面没有一页是无聊的。我希望能够理解 Orca 屏幕阅读器的代码。你的这本书有望成为我开始这项工作的装备。 -- Dattatray -> I would like to thank you for your book _A Byte of Python_ which i myself find the best way to learn python. I am a 15 year old i live in egypt my name is Ahmed. Python was my second programming language i learn visual basic 6 at school but didn't enjoy it, however i really enjoyed learning python. I made the addressbook program and i was sucessful. i will try to start make more programs and read python programs (if you could tell me source that would be helpful). I will also start on learning java and if you can tell me where to find a tutorial as good as yours for java that would help me a lot. Thanx. -> -- [Ahmed Mohammed](mailto:sedo_91@hotmail.com) +> 嗨,《简明 Python 教程》真的是一本非常好的面向 Python 初学者的教材。再次向你祝贺,**好样的**! 我是一名来自中国的有 4 年开发经验的 Java 与 C 开发者。最近,我希望能够完成一些有关 Zim-Wiki 笔记项目的工作,它是通过 pygtk 来实现的。 我用了 6 天时间读完了你的书,现在我可以读写 Python 代码范例了。 感谢您的贡献。 请保持你的热情去让这个世界变得更好,这是来自中国的微小鼓励。 -- Lee - +> 我是来自台湾的 Isen,一名台湾大学电气工程专业的博士生。我想为你这本伟大的书向你表示感谢。我认为它不仅是易于阅读,而且还为 Python 新手提供了全面而完整的内容。促使我阅读你的这本书的原因是我开始在 GNU Radio 框架下工作。 我发现你不介意读者在你的书中向你表示感谢。我十分喜欢你的这本书并对它心怀感激。谢谢你。 -- [Isen I-Chun Chao](mailto:chao926@gmail.com) -> A wonderful resource for beginners wanting to learn more about Python is the 110-page PDF tutorial A Byte of Python by Swaroop C H. It is well-written, easy to follow, and may be the best introduction to Python programming available. -> -- [Drew Ames](http://www.linux.com/feature/126522) +还有,本书已被 NASA 采用!NASA 在它们的 [喷气推进实验室(Jet Propulsion Laboratory)](http://dsnra.jpl.nasa.gov/software/Python/byte-of-python/output/byteofpython\_html/) 及它们的深空网络计划中采用了本书。 - +## 学术课程 -> Yesterday I got through most of Byte of Python on my Nokia N800 and it's the easiest and most concise introduction to Python I have yet encountered. Highly recommended as a starting point for learning Python. -> -- [Jason Delport](http://paxmodept.com/telesto/blogitem.htm?id=627) +本书曾被或正在被各类教育机构当作他们的教材: - +* [阿姆斯特丹的自由大学](http://www.few.vu.nl/\~nsilvis/PPL/2007/index.html) 的 编程语言原理(Principles of Programming Languages) 课程。 +* [加利福尼亚大学戴维斯分校](http://www.cs.ucdavis.edu/courses/exp\_course\_desc/10.html) 的 计算机运作的基本概念(Basic Concepts of Computing) 课程。 +* [哈佛大学](http://www.people.fas.harvard.edu/\~preshman/python\_winter.html) 的 Python 编程(Programming With Python) 课程。 +* [利兹大学](http://www.comp.leeds.ac.uk/acom1900/) 的 编程介绍(Introduction to Programming) 课程。 +* [波士顿大学](http://www.cs.bu.edu/courses/cs108/materials.html) 的 应用程序编程介绍(Introduction to Application Programming) 课程。 +* [俄克拉荷马大学](http://gentry.metr.ou.edu/byteofpython/) 的 气象学信息科技技能(Information Technology Skills for Meteorology) 课程。 +* [密歇根州立大学](http://www.msu.edu/\~ashton/classes/825/index.html) 的 地理处理(Geoprocessing) 课程。 +* [爱丁堡大学](http://homepages.inf.ed.ac.uk/ewan/masws/) 的 多代理语义 Web 系统(Multi Agent Semantic Web Systems) 课程。 +* [MIT 开放课程项目(MIT OpenCourseWare)](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/references/) 的 计算机科学与编程介绍(Introduction to Computer Science and Programming) 课程。 +* 斯洛文尼亚,卢布尔雅那大学的社会科学学院基础编程(Basic Programming)课程 -- [Aleš Žiberna](mailto:ales.ziberna@fdv.uni-lj.si) 说:_“我(以及我的前任)一直使用你的这本书作为课程的主要教材。”_ +* 克罗地亚,扎达尔大学信息科学系的计算机编程介绍(Introduction to programming)课程 -- Krešimir Zauder 说: _“我想告诉你,《简明 Python 教程》是我课上的强制性读物。”_ -> Byte of Vim and Python by @swaroopch is by far the best works in technical writing to me. Excellent reads #FeelGoodFactor -> -- [Surendran](http://twitter.com/suren/status/12840485454) +## 许可证 - +本书是根据 Swaroop C H 所创作的《Byte of Python》翻译而来的译本。《Byte of Python》采用 [知识共享 署名-相同方式共享 国际 4.0 协议(CC BY-SA Intl. 4.0)](http://creativecommons.org/licenses/by-sa/4.0/) 进行授权,你可以在原书的[官方网站](https://python.swaroopch.com/)上获取本书的全部原始内容。 -> "Byte of python" best one by far man -> (in response to the question "Can anyone suggest a good, inexpensive resource for learning the basics of Python? ") -> -- [Justin LoveTrue](http://www.facebook.com/pythonlang/posts/406873916788) +本译本依据相关协议进行翻译与再分发。 - +对于本译本的文本内容,采用 [知识共享 署名-相同方式共享 国际 4.0 协议(CC BY-SA Intl. 4.0)](http://creativecommons.org/licenses/by-sa/4.0/) 进行授权。 -> The Book Byte of python was very helpful ..Thanks bigtime :) -> [Chinmay](https://twitter.com/a_chinmay/status/258822633741762560) +你可以自由地: - +**分享** - 在任何媒介或格式下复制并分发本书。如转载至你的网站,或将其印刷后分发。 -> Always been a fan of A Byte of Python - made for both new and experienced programmers. -> -- [Patrick Harrington](http://stackoverflow.com/a/457785/4869) +**改编** - 对本书进行修改、重混、转换或依据本书进行再创作。如对本译本进行修改或编辑,并重新发布。 - +你可以于任何目的或环境使用本创作,即使运用于商业性用途。 -> I started learning python few days ago from your book..thanks for such a nice book. it is so well written, you made my life easy..so you found a new fan of yours..thats me :) tons of thanks. -> -- [Gadadhari Bheem](https://twitter.com/Pagal_e_azam/statuses/242865885256232960) +唯须遵循以下条件: - +**署名** - 你必须明确说明本创作、或经过修改的原创作来源于何处,并提供原始链接以及授权协议的链接。同时,除非另有许可,你不得明示或暗示你的使用行为或商业行为,来自于创作的原作者的授意或授权,或已为你的使用行为背书。 -> Before I started to learn Python, I've acquired basic programming skills in Assembly, C, C++, C# and Java. The very reason I wanted to learn Python is it's popular (people are talking about it) and powerful (reality). This book written by Mr. Swaroop is a very good guide for both brand-new programmers and new python programmers. Took 10 half days to go through it. Great Help! -> -- [Fang Biyi (PhD Candidate ECE, Michigan State University)](mailto:fangbiyi@gmail.com) +**相同方式共享** - 如果你对本书进行了修改、重混、转换,或依据本素材进行再创作,你必须采用与本书相同的许可协议来分发你的创作。 - +**不得增加额外限制** - 你不能增设任何法律限制或是技术限制,来限制他人进行本许可证已经允许的行为。 -> Thank you ever so much for this book!! -> This book cleared up many questions I had about certain aspects of Python such as object oriented programming. -> I do not feel like an expert at OO but I know this book helped me on a first step or two. -> I have now written several python programs that actually do real things for me as a system administrator. They are all procedural oriented but they are small by most peoples standards. -> Again, thanks for this book. Thank you for having it on the web. -> -- Bob +另请注意: - +* 请 _不要_ 销售本书的电子或印刷拷贝,除非你明确声明这些拷贝副本并 _非_ 来自本书的原作者。 +* 在分发时 _务必_ 在文档的介绍性描述或前页、头版中提供回溯至本书原书 \{{ book.officialUrl \}} 以及本译本 \{{book.sctransUrl\}} 的链接,并明确指出本书之原文与译本可在上述链接处获取。 +* 除非另有声明,本书所提供的所有代码与脚本均采用 [3-clause BSD License](http://www.opensource.org/licenses/bsd-license.php) 进行授权。 -> I just want to thank you for writing the first book on programming I've ever really read. Python is now my first language, and I can just imagine all the possibilities. So thank you for giving me the tools to create things I never would have imagined I could do before. -> -- "The Walrus" +## 现在就开始阅读 - +你可以通过 [http://python.swaroopch.com/](http://python.swaroopch.com/) 在线阅读本书英文原版。 -> I wanted to thank you for writing _A Byte Of Python_ (2 & 3 Versions). It has been invaluable to my learning experience in Python & Programming in general. -> Needless to say, I am a beginner in the programming world, a couple of months of self study up to this point. I had been using youtube tutorials & some other online tutorials including other free books. I decided to dig into your book yesterday, & I've learned more on the first few pages than any other book or tutorial. A few things I had been confused about, were cleared right up with a GREAT example & explanation. Can't wait to read (and learn) more!! -> Thank you so much for not only writing the book, but for putting it under the creative commons license (free). Thank goodness there are unselfish people like you out there to help & teach the rest of us. -> -- Chris +本中文译版可通过 \{{ book.sctransUrl \}} 在线阅读。 - +## 购买本书 -> I wrote you back in 2011 and I was just getting into Python and wanted to thank you for your tutorial "A Byte of Python". Without it, I would have fallen by the wayside. Since then I have gone on to program a number of functions in my organization with this language with yet more on the horizon. I would not call myself an advanced programmer by any stretch but I notice the occasional request for assistance now from others since I started using it. I discovered, while reading "Byte" why I had ceased studying C and C\++ and it was because the book given to me started out with an example containing an augmented assignment. Of course, there was no explanation for this arrangement of operators and I fell on my head trying to make sense of what was on the written page. As I recall it was a most frustrating exercise which I eventually abandoned. Doesn't mean C or C++ is impossible to learn, or even that I am stupid, but it does mean that the documentation I worked my way through did not define the symbols and words which is an essential part of any instruction. Just as computers will not be able to understand a computer word or computer symbol that is outside the syntax for the language being used, a student new to any field will not grasp his subject if he encounters words or symbols for which there are no definitions. You get a "blue screen" as it were in either case. The solution is simple, though: find the word or symbol and get the proper definition or symbol and lo and behold,the computer or student can proceed. Your book was so well put together that I found very little in it I couldn't grasp. So, thank you. I encourage you to continue to include full definitions of terms. The documentation with Python is good, once you know, (the examples are its strength from what I see) but in many cases it seems that you have to know in order to understand the documentation which to my mind is not what should be. Third party tutorials express the need for clarification of the documentation and their success largely depends on the words that are used to describe the terminology. I have recommended your book to many others. Some in Australia, some in the Caribbean and yet others in the US. It fills a niche no others do. I hope you are doing well and wish you all the success in the future. -> -- Nick +本书英文原版的印刷硬拷贝可在 [http://www.swaroopch.com/buybook/](http://www.swaroopch.com/buybook/) 购得,用以获得离线阅读体验,同时也可向本书提供支持以推进后续的开发与改进。 - +本中文译版**没有**发行或许可发行任何印刷硬拷贝。但是其他商业或非商业组织可以在遵守授权协议的前提下自行印刷并发行本书的硬拷贝,这些行为并不需要得到原作者和译者的许可。译者不会因为这些印刷或发行行为获益,亦不对这些未经专门授权的印刷或硬拷贝版本的准确性负责。 -> hey, this is ankush(19). I was facing a great difficulty to start with python. I tried a lot of books but all were bulkier and not target oriented; and then i found this lovely one, which made me love python in no time. Thanks a lot for this "beautiful piece of book". -> -- Ankush - -> I would like to thank you for your excellent guide on Python. I am a molecular biologist (with little programming background) and for my work I need to handle big datasets of DNA sequences and to analyse microscope images. For both things, programming in python has been useful, if not essential to complete and publish a 6-years project. -> That such a guide is freely available is a clear sign that the forces of evil are not yet ruling the world! :) -> -- Luca +## 在你使用的语言下阅读本书 - - -> Since this is going to be the first language you learn, you should use A Byte of Python. It really gives a proper introduction into programming in Python and it is paced well enough for the average beginner. The most important thing from then on will be actually starting to practice making your own little programs. -> -- ["{Unregistered}"](http://www.overclock.net/t/1177951/want-to-learn-programming-where-do-i-start#post_15837176) - - - -> Just to say a loud and happy _thank you very much_ for publishing "A Byte of Python" and "A Byte of Vim". Those books were very useful to me four or five years ago when I starting learning programming. Right now I'm developing a project that was a dream for a long, long time and just want to say _thank you_. Keep walking. You are a source of motivation. All the best. -> -- Jocimar - - - -> Finished reading A byte of Python in 3 days. It is thoroughly interesting. Not a single page was boring. I want to understand the Orca screen reader code. Your book has hopefully equipped me for it. -> -- Dattatray - - - -> Hi, 'A byte of python' is really a good reading for python beginners. So, again, NICE WORK! -> i'm a 4 years experienced Java&C developer from China. Recently, i want to do some work on zim-wiki note project which uses pygtk to implement. -> i read your book in 6 days, and i can read and write python code examples now. -> thx for your contribution. -> plz keep your enthusiasm to make this world better, this is just a little encourage from China. -> -- Lee - - - -> I am Isen from Taiwan, who is a graduating PhD student in Electrical Engineering Department of National Taiwan University. I would like to thank you for your great book. I think it is not only just easy to read but also comprehensive and complete for a new comer of Python. The reason I read your book is that I am starting to work on the GNU Radio framework. Your book let me catch most of important core ideas and skill of Python with a minimum time. -> I also saw that you do not mind that readers send you a thank note in your book. So I really like your book and appreciate it. Thanks. -> -- [Isen I-Chun Chao](mailto:chao926@gmail.com) - -The book is even used by NASA! It is used in their [Jet Propulsion Laboratory](http://dsnra.jpl.nasa.gov/software/Python/byte-of-python/output/byteofpython_html/) with their Deep Space Network project. - -## Academic Courses - -This book is/was being used as instructional material in various educational institutions: - -- 'Principles of Programming Languages' course at [Vrije Universiteit, Amsterdam](http://www.few.vu.nl/~nsilvis/PPL/2007/index.html) -- 'Basic Concepts of Computing' course at [University of California, Davis](http://www.cs.ucdavis.edu/courses/exp_course_desc/10.html) -- 'Programming With Python' course at [Harvard University](http://www.people.fas.harvard.edu/~preshman/python_winter.html) -- 'Introduction to Programming' course at [University of Leeds](http://www.comp.leeds.ac.uk/acom1900/) -- 'Introduction to Application Programming' course at [Boston University](http://www.cs.bu.edu/courses/cs108/materials.html) -- 'Information Technology Skills for Meteorology' course at [University of Oklahoma](http://gentry.metr.ou.edu/byteofpython/) -- 'Geoprocessing' course at [Michigan State University](http://www.msu.edu/~ashton/classes/825/index.html) -- 'Multi Agent Semantic Web Systems' course at the [University of Edinburgh](http://homepages.inf.ed.ac.uk/ewan/masws/) -- 'Introduction to Computer Science and Programming' at [MIT OpenCourseWare](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-00sc-introduction-to-computer-science-and-programming-spring-2011/references/) -- 'Basic programming at the Faculty of Social Sciences, University of Ljubljana, Slovenia' -- [Aleš Žiberna](mailto:ales.ziberna@fdv.uni-lj.si) says _"I (and my predecessor) have been using your book as the main literature for this course"_ -- 'Introduction to programming', Department of Information Sciences, University of Zadar, Croatia -- Krešimir Zauder says _"I would like to inform you that A Byte of Python is a mandatory read at my course"_ - -## License - -This book is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). - -This means: - -- You are free to Share i.e. to copy, distribute and transmit this book -- You are free to Remix i.e. to make changes to this book (especially translations) -- You are free to use it for commercial purposes - -Please note: - -- Please do *not* sell electronic or printed copies of the book unless you have clearly and prominently mentioned in the description that these copies are *not* from the original author of this book. -- Attribution *must* be shown in the introductory description and front page of the document by linking back to {{ book.officialUrl }} and clearly indicating that the original text can be fetched from this location. -- All the code/scripts provided in this book is licensed under the [3-clause BSD License](http://www.opensource.org/licenses/bsd-license.php) unless otherwise noted. - -## Read Now - -You can read it online at {{ book.officialUrl }} - -## Buy The Book - -A printed hardcopy of the book can be purchased at {{ book.buyBookUrl }} for your offline reading pleasure, and to support the continued development and improvement of this book. - -## Download - -Visit {{ book.downloadUrl }} for the following types of downloads: - -- [PDF (for desktop reading, etc.)](https://www.gitbook.com/download/pdf/book/swaroopch/byte-of-python) -- [EPUB (for iPhone/iPad, ebook readers, etc.)](https://www.gitbook.com/download/epub/book/swaroopch/byte-of-python) -- [Mobi (for Kindle)](https://www.gitbook.com/download/mobi/book/swaroopch/byte-of-python) - -Visit {{ book.sourceUrl }} for the raw content (for suggesting corrections, changes, translating, etc.) - -## Read the book in your native language - -If you are interested in reading or contributing translations of this book to other human languages, please see [Translations](./translations.md#translations). +如果你有意在其他人类语言下阅读本书,或为本书提供翻译,请参阅[翻译](23.translations.md)与[如何翻译](24.Translation-how-to.md#translation-howto)。 diff --git a/SUMMARY.md b/SUMMARY.md index b05a3796..9ead69e2 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -1,26 +1,28 @@ # Summary -* [Dedication](dedication.md) -* [Preface](preface.md) -* [About Python](about_python.md) -* [Installation](installation.md) -* [First Steps](first_steps.md) -* [Basics](basics.md) -* [Operators and Expressions](op_exp.md) -* [Control flow](control_flow.md) -* [Functions](functions.md) -* [Modules](modules.md) -* [Data Structures](data_structures.md) -* [Problem Solving](problem_solving.md) -* [Object Oriented Programming](oop.md) -* [Input and Output](io.md) -* [Exceptions](exceptions.md) -* [Standard Library](stdlib.md) -* [More](more.md) -* [What Next](what_next.md) -* [Appendix: FLOSS](floss.md) -* [Appendix: About](about.md) -* [Appendix: Revision History](revision_history.md) -* [Appendix: Translations](translations.md) -* [Appendix: Translation How-to](translation_howto.md) -* [Feedback](feedback.md) +* [介绍](README.md) +* [献词](02.dedication.md) +* [前言](03.1.preface.md) +* [译者前言](03.2.translator-preface.md) +* [关于 Python](04.about_python.md) +* [安装](05.installation.md) +* [第一步](06.first_steps.md) +* [基础](07.basics.md) +* [运算符与表达式](08.op_exp.md) +* [控制流](09.control_flow.md) +* [函数](10.functions.md) +* [模块](11.modules.md) +* [数据结构](12.data_structures.md) +* [解决问题](13.problem_solving.md) +* [面向对象编程](14.oop.md) +* [输入与输出](15.io.md) +* [异常](16.exceptions.md) +* [标准库](17.stdlib.md) +* [更多](18.more.md) +* [迈出下一步](19.what_next.md) +* [附录:FLOSS](20.floss.md) +* [附录:版本变迁](21.about.md) +* [附录:本书由来与修订历史](22.revision_history.md) +* [附录:翻译](23.translations.md) +* [附录:如何翻译](24.Translation-how-to.md) +* [反馈](25.Feedback.md) diff --git a/about.md b/about.md deleted file mode 100644 index 19ecf32c..00000000 --- a/about.md +++ /dev/null @@ -1,35 +0,0 @@ -# Appendix: Colophon {#colophon} - -Almost all of the software that I have used in the creation of this book are [FLOSS](./floss.md#floss). - -## Birth of the Book - -In the first draft of this book, I had used Red Hat 9.0 Linux as the foundation of my setup and in the sixth draft, I used Fedora Core 3 Linux as the basis of my setup. - -Initially, I was using KWord to write the book (as explained in the [history lesson](./revision_history.md#history-lesson)). - -## Teenage Years - -Later, I switched to DocBook XML using Kate but I found it too tedious. So, I switched to OpenOffice which was just excellent with the level of control it provided for formatting as well as the PDF generation, but it produced very sloppy HTML from the document. - -Finally, I discovered XEmacs and I rewrote the book from scratch in DocBook XML (again) after I decided that this format was the long term solution. - -In the sixth draft, I decided to use Quanta+ to do all the editing. The standard XSL stylesheets that came with Fedora Core 3 Linux were being used. However, I had written a CSS document to give color and style to the HTML pages. I had also written a crude lexical analyzer, in Python of course, which automatically provides syntax highlighting to all the program listings. - -For the seventh draft, I was using [MediaWiki](http://www.mediawiki.org) as the basis of my setup. I used to edit everything online and the readers can directly read/edit/discuss within the wiki website, but I ended up spending more time fighting spam than writing. - -For the eight draft, I used [Vim]({{ book.vimBookUrl }}), [Pandoc](http://johnmacfarlane.net/pandoc/README.html), and Mac OS X. - -For the ninth draft, I switched to [AsciiDoc format](http://asciidoctor.org/docs/what-is-asciidoc/) and used [Emacs 24.3](http://www.masteringemacs.org/articles/2013/03/11/whats-new-emacs-24-3/), -[tomorrow theme](https://github.com/chriskempson/tomorrow-theme), -[Fira Mono font](https://www.mozilla.org/en-US/styleguide/products/firefox-os/typeface/#download-primary) and [adoc-mode](https://github.com/sensorflo/adoc-mode/wiki) to write. - -## Now - -2016: I got tired of several minor rendering issues in AsciiDoctor, like the `++` in `C/C++` would disappear and it was hard to keep track of escaping such minor things. Plus, I had become reluctant to edit the text because of the complex Asciidoc format. - -For the tenth draft, I switched to writing in Markdown + [GitBook](https://www.gitbook.com) format, using the [Spacemacs editor](http://spacemacs.org). - -## About the Author - -See {{ book.authorUrl }} diff --git a/about_python.md b/about_python.md deleted file mode 100644 index 9bae4b47..00000000 --- a/about_python.md +++ /dev/null @@ -1,92 +0,0 @@ -# About Python - -Python is one of those rare languages which can claim to be both _simple_ and _powerful_. You will find yourself pleasantly surprised to see how easy it is to concentrate on the solution to the problem rather than the syntax and structure of the language you are programming in. - -The official introduction to Python is: - -> Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python's elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms. - -I will discuss most of these features in more detail in the next section. - -## Story behind the name - -Guido van Rossum, the creator of the Python language, named the language after the BBC show "Monty -Python's Flying Circus". He doesn't particularly like snakes that kill animals for food by winding -their long bodies around them and crushing them. - -## Features of Python - -### Simple - -Python is a simple and minimalistic language. Reading a good Python program feels almost like reading English, although very strict English! This pseudo-code nature of Python is one of its greatest strengths. It allows you to concentrate on the solution to the problem rather than the language itself. - -### Easy to Learn - -As you will see, Python is extremely easy to get started with. Python has an extraordinarily simple syntax, as already mentioned. - -### Free and Open Source - -Python is an example of a _FLOSS_ (Free/Libré and Open Source Software). In simple terms, you can freely distribute copies of this software, read its source code, make changes to it, and use pieces of it in new free programs. FLOSS is based on the concept of a community which shares knowledge. This is one of the reasons why Python is so good - it has been created and is constantly improved by a community who just want to see a better Python. - -### High-level Language - -When you write programs in Python, you never need to bother about the low-level details such as managing the memory used by your program, etc. - -### Portable - -Due to its open-source nature, Python has been ported to (i.e. changed to make it work on) many platforms. All your Python programs can work on any of these platforms without requiring any changes at all if you are careful enough to avoid any system-dependent features. - -You can use Python on GNU/Linux, Windows, FreeBSD, Macintosh, Solaris, OS/2, Amiga, AROS, AS/400, BeOS, OS/390, z/OS, Palm OS, QNX, VMS, Psion, Acorn RISC OS, VxWorks, PlayStation, Sharp Zaurus, Windows CE and PocketPC! - -You can even use a platform like [Kivy](http://kivy.org) to create games for your computer _and_ for iPhone, iPad, and Android. - -### Interpreted - -This requires a bit of explanation. - -A program written in a compiled language like C or C\++ is converted from the source language i.e. C or C++ into a language that is spoken by your computer (binary code i.e. 0s and 1s) using a compiler with various flags and options. When you run the program, the linker/loader software copies the program from hard disk to memory and starts running it. - -Python, on the other hand, does not need compilation to binary. You just _run_ the program directly from the source code. Internally, Python converts the source code into an intermediate form called bytecodes and then translates this into the native language of your computer and then runs it. All this, actually, makes using Python much easier since you don't have to worry about compiling the program, making sure that the proper libraries are linked and loaded, etc. This also makes your Python programs much more portable, since you can just copy your Python program onto another computer and it just works! - -### Object Oriented - -Python supports procedure-oriented programming as well as object-oriented programming. In _procedure-oriented_ languages, the program is built around procedures or functions which are nothing but reusable pieces of programs. In _object-oriented_ languages, the program is built around objects which combine data and functionality. Python has a very powerful but simplistic way of doing OOP, especially when compared to big languages like C++ or Java. - -### Extensible - -If you need a critical piece of code to run very fast or want to have some piece of algorithm not to be open, you can code that part of your program in C or C\++ and then use it from your Python program. - -### Embeddable - -You can embed Python within your C/C\++ programs to give _scripting_ capabilities for your program's users. - -### Extensive Libraries - -The Python Standard Library is huge indeed. It can help you do various things involving regular expressions,documentation generation, unit testing, threading, databases, web browsers, CGI, FTP, email, XML, XML-RPC, HTML, WAV files, cryptography, GUI (graphical user interfaces), and other system-dependent stuff. Remember, all this is always available wherever Python is installed. This is called the _Batteries Included_ philosophy of Python. - -Besides the standard library, there are various other high-quality libraries which you can find at the [Python Package Index](http://pypi.python.org/pypi). - -### Summary - -Python is indeed an exciting and powerful language. It has the right combination of performance and features that make writing programs in Python both fun and easy. - -## Python 3 versus 2 - -You can ignore this section if you're not interested in the difference between "Python version 2" and "Python version 3". But please do be aware of which version you are using. This book is written for Python version 3. - -Remember that once you have properly understood and learn to use one version, you can easily learn the differences and use the other one. The hard part is learning programming and understanding the basics of Python language itself. That is our goal in this book, and once you have achieved that goal, you can easily use Python 2 or Python 3 depending on your situation. - -For details on differences between Python 2 and Python 3, see: - -- [The future of Python 2](http://lwn.net/Articles/547191/) -- [Porting Python 2 Code to Python 3](https://docs.python.org/3/howto/pyporting.html) -- [Writing code that runs under both Python2 and 3](https://wiki.python.org/moin/PortingToPy3k/BilingualQuickRef) -- [Supporting Python 3: An in-depth guide](http://python3porting.com) - -## What Programmers Say - -You may find it interesting to read what great hackers like ESR have to say about Python: - -- _Eric S. Raymond_ is the author of "The Cathedral and the Bazaar" and is also the person who coined the term _Open Source_. He says that [Python has become his favorite programming language](http://www.python.org/about/success/esr/). This article was the real inspiration for my first brush with Python. -- _Bruce Eckel_ is the author of the famous 'Thinking in Java' and 'Thinking in C++' books. He says that no language has made him more productive than Python. He says that Python is perhaps the only language that focuses on making things easier for the programmer. Read the [complete interview](http://www.artima.com/intv/aboutme.html) for more details. -- _Peter Norvig_ is a well-known Lisp author and Director of Search Quality at Google (thanks to Guido van Rossum for pointing that out). He says that [writing Python is like writing in pseudocode](https://news.ycombinator.com/item?id=1803815). He says that Python has always been an integral part of Google. You can actually verify this statement by looking at the [Google Jobs](http://www.google.com/jobs/index.html) page which lists Python knowledge as a requirement for software engineers. diff --git a/basics.md b/basics.md deleted file mode 100644 index 20dbe478..00000000 --- a/basics.md +++ /dev/null @@ -1,420 +0,0 @@ -# Basics - -Just printing `hello world` is not enough, is it? You want to do more than that - you want to take some input, manipulate it and get something out of it. We can achieve this in Python using constants and variables, and we'll learn some other concepts as well in this chapter. - -## Comments - -_Comments_ are any text to the right of the `#` symbol and is mainly useful as notes for the reader of the program. - -For example: - -```python -print('hello world') # Note that print is a function -``` - -or: - -```python -# Note that print is a function -print('hello world') -``` - -Use as many useful comments as you can in your program to: - -- explain assumptions -- explain important decisions -- explain important details -- explain problems you're trying to solve -- explain problems you're trying to overcome in your program, etc. - -[*Code tells you how, comments should tell you why*](http://www.codinghorror.com/blog/2006/12/code-tells-you-how-comments-tell-you-why.html). - -This is useful for readers of your program so that they can easily understand what the program is doing. Remember, that person can be yourself after six months! - -## Literal Constants - -An example of a literal constant is a number like `5`, `1.23`, or a string like `'This is a string'` or `"It's a string!"`. - -It is called a literal because it is _literal_ - you use its value literally. The number `2` always represents itself and nothing else - it is a _constant_ because its value cannot be changed. Hence, all these are referred to as literal constants. - -## Numbers - -Numbers are mainly of two types - integers and floats. - -An examples of an integer is `2` which is just a whole number. - -Examples of floating point numbers (or _floats_ for short) are `3.23` and `52.3E-4`. The `E` notation indicates powers of 10. In this case, `52.3E-4` means `52.3 * 10^-4^`. - -> **Note for Experienced Programmers** -> -> There is no separate `long` type. The `int` type can be an integer of any size. - -## Strings - -A string is a _sequence_ of _characters_. Strings are basically just a bunch of words. - -You will be using strings in almost every Python program that you write, so pay attention to the following part. - -### Single Quote - -You can specify strings using single quotes such as `'Quote me on this'`. - -All white space i.e. spaces and tabs, within the quotes, are preserved as-is. - -### Double Quotes - -Strings in double quotes work exactly the same way as strings in single quotes. An example is `"What's your name?"`. - -### Triple Quotes {#triple-quotes} - -You can specify multi-line strings using triple quotes - (`"""` or `'''`). You can use single quotes and double quotes freely within the triple quotes. An example is: - -```python -'''This is a multi-line string. This is the first line. -This is the second line. -"What's your name?," I asked. -He said "Bond, James Bond." -''' -``` - -### Strings Are Immutable - -This means that once you have created a string, you cannot change it. Although this might seem like -a bad thing, it really isn't. We will see why this is not a limitation in the various programs that -we see later on. - -> **Note for C/C++ Programmers** -> -> There is no separate `char` data type in Python. There is no real need for it and I am sure you won't miss it. - - - -> **Note for Perl/PHP Programmers** -> -> Remember that single-quoted strings and double-quoted strings are the same - they do not differ in any way. - -### The format method - -Sometimes we may want to construct strings from other information. This is where the `format()` method is useful. - -Save the following lines as a file `str_format.py`: - -```python -age = 20 -name = 'Swaroop' - -print('{0} was {1} years old when he wrote this book'.format(name, age)) -print('Why is {0} playing with that python?'.format(name)) -``` - -Output: - -``` -$ python str_format.py -Swaroop was 20 years old when he wrote this book -Why is Swaroop playing with that python? -``` - -**How It Works** - -A string can use certain specifications and subsequently, the `format` method can be called to substitute those specifications with corresponding arguments to the `format` method. - -Observe the first usage where we use `{0}` and this corresponds to the variable `name` which is the first argument to the format method. Similarly, the second specification is `{1}` corresponding to `age` which is the second argument to the format method. Note that Python starts counting from 0 which means that first position is at index 0, second position is at index 1, and so on. - -Notice that we could have achieved the same using string concatenation: - -```python -name + ' is ' + str(age) + ' years old' -``` - -but that is much uglier and error-prone. Second, the conversion to string would be done automatically by the `format` method instead of the explicit conversion to strings needed in this case. Third, when using the `format` method, we can change the message without having to deal with the variables used and vice-versa. - -Also note that the numbers are optional, so you could have also written as: - -```python -age = 20 -name = 'Swaroop' - -print('{} was {} years old when he wrote this book'.format(name, age)) -print('Why is {} playing with that python?'.format(name)) -``` - -which will give the same exact output as the previous program. - -What Python does in the `format` method is that it substitutes each argument value into the place of the specification. There can be more detailed specifications such as: - -```python -# decimal (.) precision of 3 for float '0.333' -print('{0:.3f}'.format(1.0/3)) -# fill with underscores (_) with the text centered -# (^) to 11 width '___hello___' -print('{0:_^11}'.format('hello')) -# keyword-based 'Swaroop wrote A Byte of Python' -print('{name} wrote {book}'.format(name='Swaroop', book='A Byte of Python')) -``` - -Output: - -``` -0.333 -___hello___ -Swaroop wrote A Byte of Python -``` - -Since we are discussing formatting, note that `print` always ends with an invisible "new line" character (`\n`) so that repeated calls to `print` will all print on a separate line each. To prevent this newline character from being printed, you can specify that it should `end` with a blank: - -```python -print('a', end='') -print('b', end='') -``` - -Output is: - -``` -ab -``` - -Or you can `end` with a space: - -```python -print('a', end=' ') -print('b', end=' ') -print('c') -``` - -Output is: - -``` -a b c -``` - -### Escape Sequences - -Suppose, you want to have a string which contains a single quote (`'`), how will you specify this string? For example, the string is `"What's your name?"`. You cannot specify `'What's your name?'` because Python will be confused as to where the string starts and ends. So, you will have to specify that this single quote does not indicate the end of the string. This can be done with the help of what is called an _escape sequence_. You specify the single quote as `\'` : notice the backslash. Now, you can specify the string as `'What\'s your name?'`. - -Another way of specifying this specific string would be `"What's your name?"` i.e. using double quotes. Similarly, you have to use an escape sequence for using a double quote itself in a double quoted string. Also, you have to indicate the backslash itself using the escape sequence `\\`. - -What if you wanted to specify a two-line string? One way is to use a triple-quoted string as shown [previously](#triple-quotes) or you can use an escape sequence for the newline character - `\n` to indicate the start of a new line. An example is: - -```python -'This is the first line\nThis is the second line' -``` - -Another useful escape sequence to know is the tab: `\t`. There are many more escape sequences but I have mentioned only the most useful ones here. - -One thing to note is that in a string, a single backslash at the end of the line indicates that the string is continued in the next line, but no newline is added. For example: - -```python -"This is the first sentence. \ -This is the second sentence." -``` - -is equivalent to - -```python -"This is the first sentence. This is the second sentence." -``` - -### Raw String - -If you need to specify some strings where no special processing such as escape sequences are handled, then what you need is to specify a _raw_ string by prefixing `r` or `R` to the string. An example is: - -```python -r"Newlines are indicated by \n" -``` - -> **Note for Regular Expression Users** -> -> Always use raw strings when dealing with regular expressions. Otherwise, a lot of backwhacking may be required. For example, backreferences can be referred to as `'\\1'` or `r'\1'`. - -## Variable - -Using just literal constants can soon become boring - we need some way of storing any information and manipulate them as well. This is where _variables_ come into the picture. Variables are exactly what the name implies - their value can vary, i.e., you can store anything using a variable. Variables are just parts of your computer's memory where you store some information. Unlike literal constants, you need some method of accessing these variables and hence you give them names. - -## Identifier Naming - -Variables are examples of identifiers. _Identifiers_ are names given to identify _something_. There are some rules you have to follow for naming identifiers: - -- The first character of the identifier must be a letter of the alphabet (uppercase ASCII or lowercase ASCII or Unicode character) or an underscore (`_`). -- The rest of the identifier name can consist of letters (uppercase ASCII or lowercase ASCII or Unicode character), underscores (`_`) or digits (0-9). -- Identifier names are case-sensitive. For example, `myname` and `myName` are _not_ the same. Note the lowercase `n` in the former and the uppercase `N` in the latter. -- Examples of _valid_ identifier names are `i`, `name_2_3`. Examples of _invalid_ identifier names are `2things`, `this is spaced out`, `my-name` and `>a1b2_c3`. - -## Data Types - -Variables can hold values of different types called _data types_. The basic types are numbers and strings, which we have already discussed. In later chapters, we will see how to create our own types using [classes](./oop.md#classes). - -## Object - -Remember, Python refers to anything used in a program as an _object_. This is meant in the generic sense. Instead of saying "the _something_"', we say "the _object_". - -> **Note for Object Oriented Programming users**: -> -> Python is strongly object-oriented in the sense that everything is an object including numbers, strings and functions. - -We will now see how to use variables along with literal constants. Save the following example and run the program. - -## How to write Python programs - -Henceforth, the standard procedure to save and run a Python program is as follows: - -### For PyCharm - -1. Open [PyCharm](./first_steps.md#pycharm). -2. Create new file with the filename mentioned. -3. Type the program code given in the example. -4. Right-click and run the current file. - -NOTE: Whenever you have to provide [command line arguments](./modules.md#modules), click on `Run` -> `Edit Configurations` and type the arguments in the `Script parameters:` section and click the `OK` button: - -![PyCharm command line arguments](./img/pycharm_command_line_arguments.png) - -### For other editors - -1. Open your editor of choice. -2. Type the program code given in the example. -3. Save it as a file with the filename mentioned. -4. Run the interpreter with the command `python program.py` to run the program. - -### Example: Using Variables And Literal Constants - -Type and run the following program: - -```python -# Filename : var.py -i = 5 -print(i) -i = i + 1 -print(i) - -s = '''This is a multi-line string. -This is the second line.''' -print(s) -``` - -Output: - -``` -5 -6 -This is a multi-line string. -This is the second line. -``` - -**How It Works** - -Here's how this program works. First, we assign the literal constant value `5` to the variable `i` using the assignment operator (`=`). This line is called a statement because it states that something should be done and in this case, we connect the variable name `i` to the value `5`. Next, we print the value of `i` using the `print` statement which, unsurprisingly, just prints the value of the variable to the screen. - -Then we add `1` to the value stored in `i` and store it back. We then print it and expectedly, we get the value `6`. - -Similarly, we assign the literal string to the variable +s+ and then print it. - -> **Note for static language programmers** -> -> Variables are used by just assigning them a value. No declaration or data type definition is needed/used. - -## Logical And Physical Line - -A physical line is what you _see_ when you write the program. A logical line is what _Python sees_ as a single statement. Python implicitly assumes that each _physical line_ corresponds to a _logical line_. - -An example of a logical line is a statement like `print 'hello world'` - if this was on a line by itself (as you see it in an editor), then this also corresponds to a physical line. - -Implicitly, Python encourages the use of a single statement per line which makes code more readable. - -If you want to specify more than one logical line on a single physical line, then you have to explicitly specify this using a semicolon (`;`) which indicates the end of a logical line/statement. For example: - -```python -i = 5 -print(i) -``` - -is effectively same as - -```python -i = 5; -print(i); -``` - -which is also same as - -```python -i = 5; print(i); -``` - -and same as - -```python -i = 5; print(i) -``` - -However, I *strongly recommend* that you stick to *writing a maximum of a single logical line on each single physical line*. The idea is that you should never use the semicolon. In fact, I have _never_ used or even seen a semicolon in a Python program. - -There is one kind of situation where this concept is really useful: if you have a long line of code, you can break it into multiple physical lines by using the backslash. This is referred to as _explicit line joining_: - -```python -s = 'This is a string. \ -This continues the string.' -print(s) -``` - -Output: - -``` -This is a string. This continues the string. -``` - -Similarly, - -```python -i = \ -5 -``` - -is the same as - -```python -i = 5 -``` - -Sometimes, there is an implicit assumption where you don't need to use a backslash. This is the case where the logical line has a starting parentheses, starting square brackets or a starting curly braces but not an ending one. This is called *implicit line joining*. You can see this in action when we write programs using [list](./data_structures.md#lists) in later chapters. - -## Indentation - -Whitespace is important in Python. Actually, *whitespace at the beginning of the line is important*. This is called _indentation_. Leading whitespace (spaces and tabs) at the beginning of the logical line is used to determine the indentation level of the logical line, which in turn is used to determine the grouping of statements. - -This means that statements which go together _must_ have the same indentation. Each such set of statements is called a *block*. We will see examples of how blocks are important in later chapters. - -One thing you should remember is that wrong indentation can give rise to errors. For example: - -```python -i = 5 -# Error below! Notice a single space at the start of the line - print('Value is', i) -print('I repeat, the value is', i) -``` - -When you run this, you get the following error: - -``` - File "whitespace.py", line 3 - print('Value is', i) - ^ -IndentationError: unexpected indent -``` - -Notice that there is a single space at the beginning of the second line. The error indicated by Python tells us that the syntax of the program is invalid i.e. the program was not properly written. What this means to you is that _you cannot arbitrarily start new blocks of statements_ (except for the default main block which you have been using all along, of course). Cases where you can use new blocks will be detailed in later chapters such as the [control flow](./control_flow.md#control_flow). - -> **How to indent** -> -> Use four spaces for indentation. This is the official Python language recommendation. Good editors will automatically do this for you. Make sure you use a consistent number of spaces for indentation, otherwise your program will not run or will have unexpected behavior. - - - -> **Note to static language programmers** -> -> Python will always use indentation for blocks and will never use braces. Run `from __future__ import braces` to learn more. - -## Summary - -Now that we have gone through many nitty-gritty details, we can move on to more interesting stuff such as control flow statements. Be sure to become comfortable with what you have read in this chapter. - diff --git a/book.json b/book.json index 4f16cacf..578cbca9 100644 --- a/book.json +++ b/book.json @@ -1,5 +1,9 @@ { - "variables": { + "plugins": [ + "betterchinese" + ], + "pluginsConfig": {}, + "variables": { "authorUrl": "http://www.swaroopch.com/about/", "buyBookUrl": "http://www.swaroopch.com/buybook/", "contactUrl": "http://www.swaroopch.com/contact/", @@ -7,6 +11,11 @@ "officialUrl": "http://python.swaroopch.com/", "pythonVersion": "3.5.1", "sourceUrl": "https://github.com/swaroopch/byte-of-python", - "vimBookUrl": "http://vim.swaroopch.com/" + "vimBookUrl": "http://vim.swaroopch.com/", + "sctransUrl": "https://bop.mol.uno", + "translator": "https://molun.net", + "transdownloadurl": "https://www.gitbook.com/book/lenkimo/byte-of-python-chinese-edition/", + "transsourceurl": "https://github.com/LenKiMo/byte-of-python" } -} + +} \ No newline at end of file diff --git a/control_flow.md b/control_flow.md deleted file mode 100644 index bc986293..00000000 --- a/control_flow.md +++ /dev/null @@ -1,166 +0,0 @@ -# Control Flow {#control-flow} - -In the programs we have seen till now, there has always been a series of statements faithfully executed by Python in exact top-down order. What if you wanted to change the flow of how it works? For example, you want the program to take some decisions and do different things depending on different situations, such as printing 'Good Morning' or 'Good Evening' depending on the time of the day? - -As you might have guessed, this is achieved using control flow statements. There are three control flow statements in Python - `if`, `for` and `while`. - -## The `if` statement - -The `if` statement is used to check a condition: *if* the condition is true, we run a block of statements (called the _if-block_), *else* we process another block of statements (called the _else-block_). The *else* clause is optional. - -Example (save as `if.py`): - - -
{% include "./programs/if.py" %}
- -Output: - -
{% include "./programs/if.txt" %}
- -**How It Works** - -In this program, we take guesses from the user and check if it is the number that we have. We set the variable +number+ to any integer we want, say `23`. Then, we take the user's guess using the `input()` function. Functions are just reusable pieces of programs. We'll read more about them in the [next chapter](./functions.md#functions). - -We supply a string to the built-in `input` function which prints it to the screen and waits for input from the user. Once we enter something and press kbd:[enter] key, the `input()` function returns what we entered, as a string. We then convert this string to an integer using `int` and then store it in the variable `guess`. Actually, the `int` is a class but all you need to know right now is that you can use it to convert a string to an integer (assuming the string contains a valid integer in the text). - -Next, we compare the guess of the user with the number we have chosen. If they are equal, we print a success message. Notice that we use indentation levels to tell Python which statements belong to which block. This is why indentation is so important in Python. I hope you are sticking to the "consistent indentation" rule. Are you? - -Notice how the `if` statement contains a colon at the end - we are indicating to Python that a block of statements follows. - -Then, we check if the guess is less than the number, and if so, we inform the user that they must guess a little higher than that. What we have used here is the `elif` clause which actually combines two related `if else-if else` statements into one combined `if-elif-else` statement. This makes the program easier and reduces the amount of indentation required. - -The `elif` and `else` statements must also have a colon at the end of the logical line followed by their corresponding block of statements (with proper indentation, of course) - -You can have another `if` statement inside the if-block of an `if` statement and so on - this is called a nested `if` statement. - -Remember that the `elif` and `else` parts are optional. A minimal valid `if` statement is: - -```python -if True: - print('Yes, it is true') -``` - -After Python has finished executing the complete `if` statement along with the associated `elif` and `else` clauses, it moves on to the next statement in the block containing the `if` statement. In this case, it is the main block (where execution of the program starts), and the next statement is the `print('Done')` statement. After this, Python sees the ends of the program and simply finishes up. - -Even though this is a very simple program, I have been pointing out a lot of things that you should notice. All these are pretty straightforward (and surprisingly simple for those of you from C/C++ backgrounds). You will need to become aware of all these things initially, but after some practice you will become comfortable with them, and it will all feel 'natural' to you. - -> **Note for C/C++ Programmers** -> -> There is no `switch` statement in Python. You can use an `if..elif..else` statement to do the same thing (and in some cases, use a [dictionary](./data_structures.md#dictionary) to do it quickly) - -## The while Statement - -The `while` statement allows you to repeatedly execute a block of statements as long as a condition is true. A `while` statement is an example of what is called a *looping* statement. A `while` statement can have an optional `else` clause. - -Example (save as `while.py`): - -
{% include "./programs/while.py" %}
- -Output: - -
{% include "./programs/while.txt" %}
- -**How It Works** - -In this program, we are still playing the guessing game, but the advantage is that the user is allowed to keep guessing until he guesses correctly - there is no need to repeatedly run the program for each guess, as we have done in the previous section. This aptly demonstrates the use of the `while` statement. - -We move the `input` and `if` statements to inside the `while` loop and set the variable `running` to `True` before the while loop. First, we check if the variable `running` is `True` and then proceed to execute the corresponding *while-block*. After this block is executed, the condition is again checked which in this case is the `running` variable. If it is true, we execute the while-block again, else we continue to execute the optional else-block and then continue to the next statement. - -The `else` block is executed when the `while` loop condition becomes `False` - this may even be the first time that the condition is checked. If there is an `else` clause for a `while` loop, it is always executed unless you break out of the loop with a `break` statement. - -The `True` and `False` are called Boolean types and you can consider them to be equivalent to the value `1` and `0` respectively. - -> **Note for C/C++ Programmers** -> -> Remember that you can have an `else` clause for the `while` loop. - -## The `for` loop - -The `for..in` statement is another looping statement which *iterates* over a sequence of objects i.e. go through each item in a sequence. We will see more about [sequences](./data_structures.md#sequence) in detail in later chapters. What you need to know right now is that a sequence is just an ordered collection of items. - -Example (save as `for.py`): - -
{% include "./programs/for.py" %}
- -Output: - -
{% include "./programs/for.txt" %}
- -**How It Works** - -In this program, we are printing a *sequence* of numbers. We generate this sequence of numbers using the built-in `range` function. - -What we do here is supply it two numbers and `range` returns a sequence of numbers starting from the first number and up to the second number. For example, `range(1,5)` gives the sequence `[1, 2, 3, 4]`. By default, `range` takes a step count of 1. If we supply a third number to `range`, then that becomes the step count. For example, `range(1,5,2)` gives `[1,3]`. Remember that the range extends *up to* the second number i.e. it does *not* include the second number. - -Note that `range()` generates only one number at a time, if you want the full list of numbers, call `list()` on the `range()`, for example, `list(range(5))` will result in `[0, 1, 2, 3, 4]`. Lists are explained in the [data structures chapter](./data_structures.md#data-structures). - -The `for` loop then iterates over this range - `for i in range(1,5)` is equivalent to `for i in [1, 2, 3, 4]` which is like assigning each number (or object) in the sequence to i, one at a time, and then executing the block of statements for each value of `i`. In this case, we just print the value in the block of statements. - -Remember that the `else` part is optional. When included, it is always executed once after the `for` loop is over unless a <> statement is encountered. - -Remember that the `for..in` loop works for any sequence. Here, we have a list of numbers generated by the built-in `range` function, but in general we can use any kind of sequence of any kind of objects! We will explore this idea in detail in later chapters. - -> **Note for C/C++/Java/C# Programmers** -> -> The Python `for` loop is radically different from the C/C++ `for` loop. C# programmers will note that the `for` loop in Python is similar to the `foreach` loop in C#. Java programmers will note that the same is similar to `for (int i : IntArray)` in Java 1.5. -> -> In C/C++, if you want to write `for (int i = 0; i < 5; i++)`, then in Python you write just `for i in range(0,5)`. As you can see, the `for` loop is simpler, more expressive and less error prone in Python. - -## The break Statement {#break-statement} - -The `break` statement is used to *break* out of a loop statement i.e. stop the execution of a looping statement, even if the loop condition has not become `False` or the sequence of items has not been completely iterated over. - -An important note is that if you *break* out of a `for` or `while` loop, any corresponding loop `else` block is **not** executed. - -Example (save as `break.py`): - -
{% include "./programs/break.py" %}
- -Output: - -
{% include "./programs/break.txt" %}
- -**How It Works** - -In this program, we repeatedly take the user's input and print the length of each input each -time. We are providing a special condition to stop the program by checking if the user input is -`'quit'`. We stop the program by *breaking* out of the loop and reach the end of the program. - -The length of the input string can be found out using the built-in `len` function. - -Remember that the `break` statement can be used with the `for` loop as well. - -**Swaroop's Poetic Python** - -The input I have used here is a mini poem I have written: - -``` -Programming is fun -When the work is done -if you wanna make your work also fun: - use Python! -``` - -## The `continue` Statement {#continue-statement} - -The `continue` statement is used to tell Python to skip the rest of the statements in the current loop block and to *continue* to the next iteration of the loop. - -Example (save as `continue.py`): - -
{% include "./programs/continue.py" %}
- -Output: - -
{% include "./programs/continue.txt" %}
- -**How It Works** - -In this program, we accept input from the user, but we process the input string only if it is at least 3 characters long. So, we use the built-in `len` function to get the length and if the length is less than 3, we skip the rest of the statements in the block by using the `continue` statement. Otherwise, the rest of the statements in the loop are executed, doing any kind of processing we want to do here. - -Note that the `continue` statement works with the `for` loop as well. - -## Summary - -We have seen how to use the three control flow statements - `if`, `while` and `for` along with their associated `break` and `continue` statements. These are some of the most commonly used parts of Python and hence, becoming comfortable with them is essential. - -Next, we will see how to create and use functions. diff --git a/data_structures.md b/data_structures.md deleted file mode 100644 index b243b025..00000000 --- a/data_structures.md +++ /dev/null @@ -1,240 +0,0 @@ -# Data Structures {#data-structures} - -Data structures are basically just that - they are *structures* which can hold some *data* together. In other words, they are used to store a collection of related data. - -There are four built-in data structures in Python - _list, tuple, dictionary and set_. We will see how to use each of them and how they make life easier for us. - -## List - -A `list` is a data structure that holds an ordered collection of items i.e. you can store a *sequence* of items in a list. This is easy to imagine if you can think of a shopping list where you have a list of items to buy, except that you probably have each item on a separate line in your shopping list whereas in Python you put commas in between them. - -The list of items should be enclosed in square brackets so that Python understands that you are specifying a list. Once you have created a list, you can add, remove or search for items in the list. Since we can add and remove items, we say that a list is a *mutable* data type i.e. this type can be altered. - -## Quick Introduction To Objects And Classes - -Although I've been generally delaying the discussion of objects and classes till now, a little explanation is needed right now so that you can understand lists better. We will explore this topic in detail in a [later chapter](./oop.md#oop). - -A list is an example of usage of objects and classes. When we use a variable `i` and assign a value to it, say integer `5` to it, you can think of it as creating an *object* (i.e. instance) `i` of *class* (i.e. type) `int`. In fact, you can read `help(int)` to understand this better. - -A class can also have *methods* i.e. functions defined for use with respect to that class only. You can use these pieces of functionality only when you have an object of that class. For example, Python provides an `append` method for the `list` class which allows you to add an item to the end of the list. For example, `mylist.append('an item')` will add that string to the list `mylist`. Note the use of dotted notation for accessing methods of the objects. - -A class can also have *fields* which are nothing but variables defined for use with respect to that class only. You can use these variables/names only when you have an object of that class. Fields are also accessed by the dotted notation, for example, `mylist.field`. - -Example (save as `ds_using_list.py`): - -
{% include "./programs/ds_using_list.py" %}
- -Output: - -
{% include "./programs/ds_using_list.txt" %}
- -**How It Works** - -The variable `shoplist` is a shopping list for someone who is going to the market. In `shoplist`, we only store strings of the names of the items to buy but you can add _any kind of object_ to a list including numbers and even other lists. - -We have also used the `for..in` loop to iterate through the items of the list. By now, you must have realised that a list is also a sequence. The speciality of sequences will be discussed in a [later section](#sequence). - -Notice the use of the `end` parameter in the call to `print` function to indicate that we want to end the output with a space instead of the usual line break. - -Next, we add an item to the list using the `append` method of the list object, as already discussed before. Then, we check that the item has been indeed added to the list by printing the contents of the list by simply passing the list to the `print` function which prints it neatly. - -Then, we sort the list by using the `sort` method of the list. It is important to understand that this method affects the list itself and does not return a modified list - this is different from the way strings work. This is what we mean by saying that lists are _mutable_ and that strings are _immutable_. - -Next, when we finish buying an item in the market, we want to remove it from the list. We achieve this by using the `del` statement. Here, we mention which item of the list we want to remove and the `del` statement removes it from the list for us. We specify that we want to remove the first item from the list and hence we use `del shoplist[0]` (remember that Python starts counting from 0). - -If you want to know all the methods defined by the list object, see `help(list)` for details. - -## Tuple - -Tuples are used to hold together multiple objects. Think of them as similar to lists, but without the extensive functionality that the list class gives you. One major feature of tuples is that they are *immutable* like strings i.e. you cannot modify tuples. - -Tuples are defined by specifying items separated by commas within an optional pair of parentheses. - -Tuples are usually used in cases where a statement or a user-defined function can safely assume that the collection of values i.e. the tuple of values used will not change. - -Example (save as `ds_using_tuple.py`): - -
{% include "./programs/ds_using_tuple.py" %}
- -Output: - -
{% include "./programs/ds_using_tuple.txt" %}
- -**How It Works** - -The variable `zoo` refers to a tuple of items. We see that the `len` function can be used to get the length of the tuple. This also indicates that a tuple is a [sequence](#sequence) as well. - -We are now shifting these animals to a new zoo since the old zoo is being closed. Therefore, the `new_zoo` tuple contains some animals which are already there along with the animals brought over from the old zoo. Back to reality, note that a tuple within a tuple does not lose its identity. - -We can access the items in the tuple by specifying the item's position within a pair of square brackets just like we did for lists. This is called the _indexing_ operator. We access the third item in `new_zoo` by specifying `new_zoo[2]` and we access the third item within the third item in the `new_zoo` tuple by specifying `new_zoo[2][2]`. This is pretty simple once you've understood the idiom. - -> **Tuple with 0 or 1 items** -> -> An empty tuple is constructed by an empty pair of parentheses such as `myempty = ()`. However, a tuple with a single item is not so simple. You have to specify it using a comma following the first (and only) item so that Python can differentiate between a tuple and a pair of parentheses surrounding the object in an expression i.e. you have to specify `singleton = (2 , )` if you mean you want a tuple containing the item `2`. - - - -> **Note for Perl programmers** -> -> A list within a list does not lose its identity i.e. lists are not flattened as in Perl. The same applies to a tuple within a tuple, or a tuple within a list, or a list within a tuple, etc. As far as Python is concerned, they are just objects stored using another object, that's all. - -## Dictionary - -A dictionary is like an address-book where you can find the address or contact details of a person by knowing only his/her name i.e. we associate *keys* (name) with *values* (details). Note that the key must be unique just like you cannot find out the correct information if you have two persons with the exact same name. - -Note that you can use only immutable objects (like strings) for the keys of a dictionary but you can use either immutable or mutable objects for the values of the dictionary. This basically translates to say that you should use only simple objects for keys. - -Pairs of keys and values are specified in a dictionary by using the notation `d = {key1 : value1, key2 : value2 }`. Notice that the key-value pairs are separated by a colon and the pairs are separated themselves by commas and all this is enclosed in a pair of curly braces. - -Remember that key-value pairs in a dictionary are not ordered in any manner. If you want a particular order, then you will have to sort them yourself before using it. - -The dictionaries that you will be using are instances/objects of the `dict` class. - -Example (save as `ds_using_dict.py`): - -
{% include "./programs/ds_using_dict.py" %}
- -Output: - -
{% include "./programs/ds_using_dict.txt" %}
- -**How It Works** - -We create the dictionary `ab` using the notation already discussed. We then access key-value pairs by specifying the key using the indexing operator as discussed in the context of lists and tuples. Observe the simple syntax. - -We can delete key-value pairs using our old friend - the `del` statement. We simply specify the dictionary and the indexing operator for the key to be removed and pass it to the `del` statement. There is no need to know the value corresponding to the key for this operation. - -Next, we access each key-value pair of the dictionary using the `items` method of the dictionary which returns a list of tuples where each tuple contains a pair of items - the key followed by the value. We retrieve this pair and assign it to the variables `name` and `address` correspondingly for each pair using the `for..in` loop and then print these values in the for-block. - -We can add new key-value pairs by simply using the indexing operator to access a key and assign that value, as we have done for Guido in the above case. - -We can check if a key-value pair exists using the `in` operator. - -For the list of methods of the `dict` class, see `help(dict)`. - -> **Keyword Arguments and Dictionaries** -> -> If you have used keyword arguments in your functions, you have already used dictionaries! Just think about it - the key-value pair is specified by you in the parameter list of the function definition and when you access variables within your function, it is just a key access of a dictionary (which is called the _symbol table_ in compiler design terminology). - -## Sequence - -Lists, tuples and strings are examples of sequences, but what are sequences and what is so special about them? - -The major features are *membership tests*, (i.e. the `in` and `not in` expressions) and *indexing operations*, which allow us to fetch a particular item in the sequence directly. - -The three types of sequences mentioned above - lists, tuples and strings, also have a *slicing* operation which allows us to retrieve a slice of the sequence i.e. a part of the sequence. - -Example (save as `ds_seq.py`): - -
{% include "./programs/ds_seq.py" %}
- -Output: - -
{% include "./programs/ds_seq.txt" %}
- -**How It Works** - -First, we see how to use indexes to get individual items of a sequence. This is also referred to as the _subscription operation_. Whenever you specify a number to a sequence within square brackets as shown above, Python will fetch you the item corresponding to that position in the sequence. Remember that Python starts counting numbers from 0. Hence, `shoplist[0]` fetches the first item and `shoplist[3]` fetches the fourth item in the `shoplist`sequence. - -The index can also be a negative number, in which case, the position is calculated from the end of the sequence. Therefore, `shoplist[-1]` refers to the last item in the sequence and `shoplist[-2]` fetches the second last item in the sequence. - -The slicing operation is used by specifying the name of the sequence followed by an optional pair of numbers separated by a colon within square brackets. Note that this is very similar to the indexing operation you have been using till now. Remember the numbers are optional but the colon isn't. - -The first number (before the colon) in the slicing operation refers to the position from where the slice starts and the second number (after the colon) indicates where the slice will stop at. If the first number is not specified, Python will start at the beginning of the sequence. If the second number is left out, Python will stop at the end of the sequence. Note that the slice returned _starts_ at the start position and will end just before the _end_ position i.e. the start position is included but the end position is excluded from the sequence slice. - -Thus, `shoplist[1:3]` returns a slice of the sequence starting at position 1, includes position 2 but stops at position 3 and therefore a *slice* of two items is returned. Similarly, `shoplist[:]` returns a copy of the whole sequence. - -You can also do slicing with negative positions. Negative numbers are used for positions from the end of the sequence. For example, `shoplist[:-1]` will return a slice of the sequence which excludes the last item of the sequence but contains everything else. - -You can also provide a third argument for the slice, which is the _step_ for the slicing (by default, the step size is 1): - -```python ->>> shoplist = ['apple', 'mango', 'carrot', 'banana'] ->>> shoplist[::1] -['apple', 'mango', 'carrot', 'banana'] ->>> shoplist[::2] -['apple', 'carrot'] ->>> shoplist[::3] -['apple', 'banana'] ->>> shoplist[::-1] -['banana', 'carrot', 'mango', 'apple'] -``` - -Notice that when the step is 2, we get the items with position 0, 2,... When the step size is 3, we get the items with position 0, 3, etc. - -Try various combinations of such slice specifications using the Python interpreter interactively i.e. the prompt so that you can see the results immediately. The great thing about sequences is that you can access tuples, lists and strings all in the same way! - -## Set - -Sets are _unordered_ collections of simple objects. These are used when the existence of an object in a collection is more important than the order or how many times it occurs. - -Using sets, you can test for membership, whether it is a subset of another set, find the intersection between two sets, and so on. - -```python ->>> bri = set(['brazil', 'russia', 'india']) ->>> 'india' in bri -True ->>> 'usa' in bri -False ->>> bric = bri.copy() ->>> bric.add('china') ->>> bric.issuperset(bri) -True ->>> bri.remove('russia') ->>> bri & bric # OR bri.intersection(bric) -{'brazil', 'india'} -``` - -**How It Works** - -The example is pretty much self-explanatory because it involves basic set theory mathematics taught in school. - -## References - -When you create an object and assign it to a variable, the variable only _refers_ to the object and does not represent the object itself! That is, the variable name points to that part of your computer's memory where the object is stored. This is called *binding* the name to the object. - -Generally, you don't need to be worried about this, but there is a subtle effect due to references which you need to be aware of: - -Example (save as `ds_reference.py`): - -
{% include "./programs/ds_reference.py" %}
- -Output: - -
{% include "./programs/ds_reference.txt" %}
- -**How It Works** - -Most of the explanation is available in the comments. - -Remember that if you want to make a copy of a list or such kinds of sequences or complex objects (not simple _objects_ such as integers), then you have to use the slicing operation to make a copy. If you just assign the variable name to another name, both of them will ''refer'' to the same object and this could be trouble if you are not careful. - -> **Note for Perl programmers** -> -> Remember that an assignment statement for lists does **not** create a copy. You have to use slicing operation to make a copy of the sequence. - -## More About Strings {#more-strings} - -We have already discussed strings in detail earlier. What more can there be to know? Well, did you know that strings are also objects and have methods which do everything from checking part of a string to stripping spaces! - -The strings that you use in program are all objects of the class `str`. Some useful methods of this class are demonstrated in the next example. For a complete list of such methods, see `help(str)`. - -Example (save as `ds_str_methods.py`): - -
{% include "./programs/ds_str_methods.py" %}
- -Output: - -
{% include "./programs/ds_str_methods.txt" %}
- -**How It Works** - -Here, we see a lot of the string methods in action. The `startswith` method is used to find out whether the string starts with the given string. The `in` operator is used to check if a given string is a part of the string. - -The `find` method is used to locate the position of the given substring within the string; `find` returns -1 if it is unsuccessful in finding the substring. The `str` class also has a neat method to `join` the items of a sequence with the string acting as a delimiter between each item of the sequence and returns a bigger string generated from this. - -## Summary - -We have explored the various built-in data structures of Python in detail. These data structures will be essential for writing programs of reasonable size. - -Now that we have a lot of the basics of Python in place, we will next see how to design and write a real-world Python program. diff --git a/dedication.md b/dedication.md deleted file mode 100644 index fdd08cfe..00000000 --- a/dedication.md +++ /dev/null @@ -1,7 +0,0 @@ -# Dedication - -To [Kalyan Varma](http://www.kalyanvarma.net/) and many other seniors at [PESIT](http://www.pes.edu/) who introduced us to GNU/Linux and the world of open source. - -To the memory of [Atul Chitnis](http://www.nextbigwhat.com/atul-chitnis-obituary-297/), a friend and guide who shall be missed greatly. - -To the [pioneers who made the Internet happen](http://www.ibiblio.org/pioneers/index.html). This book was first written in 2003. It still remains popular, thanks to the nature of sharing knowledge on the Internet as envisioned by the pioneers. diff --git a/exceptions.md b/exceptions.md deleted file mode 100644 index 5e129ceb..00000000 --- a/exceptions.md +++ /dev/null @@ -1,123 +0,0 @@ -# Exceptions - -Exceptions occur when _exceptional_ situations occur in your program. For example, what if you are going to read a file and the file does not exist? Or what if you accidentally deleted it when the program was running? Such situations are handled using **exceptions**. - -Similarly, what if your program had some invalid statements? This is handled by Python which **raises** its hands and tells you there is an **error**. - -## Errors - -Consider a simple `print` function call. What if we misspelt `print` as `Print`? Note the capitalization. In this case, Python _raises_ a syntax error. - -```python ->>> Print("Hello World") -Traceback (most recent call last): - File "", line 1, in -NameError: name 'Print' is not defined ->>> print("Hello World") -Hello World -``` - -Observe that a `NameError` is raised and also the location where the error was detected is printed. This is what an **error handler** for this error does. - -## Exceptions - -We will **try** to read input from the user. Press `[ctrl-d]` and see what happens. - -```python ->>> s = input('Enter something --> ') -Enter something --> Traceback (most recent call last): - File "", line 1, in -EOFError -``` - -Python raises an error called `EOFError` which basically means it found an *end of file* symbol (which is represented by `ctrl-d`) when it did not expect to see it. - -## Handling Exceptions - -We can handle exceptions using the `try..except` statement. We basically put our usual statements within the try-block and put all our error handlers in the except-block. - -Example (save as `exceptions_handle.py`): - -
{% include "./programs/exceptions_handle.py" %}
- -Output: - -
{% include "./programs/exceptions_handle.txt" %}
- -**How It Works** - -We put all the statements that might raise exceptions/errors inside the `try` block and then put handlers for the appropriate errors/exceptions in the `except` clause/block. The `except` clause can handle a single specified error or exception, or a parenthesized list of errors/exceptions. If no names of errors or exceptions are supplied, it will handle _all_ errors and exceptions. - -Note that there has to be at least one `except` clause associated with every `try` clause. Otherwise, what's the point of having a try block? - -If any error or exception is not handled, then the default Python handler is called which just stops the execution of the program and prints an error message. We have already seen this in action above. - -You can also have an `else` clause associated with a `try..except` block. The `else` clause is executed if no exception occurs. - -In the next example, we will also see how to get the exception object so that we can retrieve additional information. - -## Raising Exceptions - -You can _raise_ exceptions using the `raise` statement by providing the name of the error/exception and the exception object that is to be _thrown_. - -The error or exception that you can raise should be a class which directly or indirectly must be a derived class of the `Exception` class. - -Example (save as `exceptions_raise.py`): - -
{% include "./programs/exceptions_raise.py" %}
- -Output: - -
{% include "./programs/exceptions_raise.txt" %}
- -**How It Works** - -Here, we are creating our own exception type. This new exception type is called `ShortInputException`. It has two fields - `length` which is the length of the given input, and `atleast` which is the minimum length that the program was expecting. - -In the `except` clause, we mention the class of error which will be stored `as` the variable name to hold the corresponding error/exception object. This is analogous to parameters and arguments in a function call. Within this particular `except` clause, we use the `length` and `atleast` fields of the exception object to print an appropriate message to the user. - -## Try ... Finally {#try-finally} - -Suppose you are reading a file in your program. How do you ensure that the file object is closed properly whether or not an exception was raised? This can be done using the `finally` block. - -Save this program as `exceptions_finally.py`: - -
{% include "./programs/exceptions_finally.py" %}
- -Output: - -
{% include "./programs/exceptions_finally.txt" %}
- -**How It Works** - -We do the usual file-reading stuff, but we have arbitrarily introduced sleeping for 2 seconds after printing each line using the `time.sleep` function so that the program runs slowly (Python is very fast by nature). When the program is still running, press `ctrl + c` to interrupt/cancel the program. - -Observe that the `KeyboardInterrupt` exception is thrown and the program quits. However, before the program exits, the finally clause is executed and the file object is always closed. - -Note that we use `sys.stdout.flush()` after `print` so that it prints to the screen immediately. - -## The with statement {#with} - -Acquiring a resource in the `try` block and subsequently releasing the resource in the `finally` block is a common pattern. Hence, there is also a `with` statement that enables this to be done in a clean manner: - -Save as `exceptions_using_with.py`: - -
{% include "./programs/exceptions_using_with.py" %}
- -**How It Works** - -The output should be same as the previous example. The difference here is that we are using the `open` function with the `with` statement - we leave the closing of the file to be done automatically by `with open`. - -What happens behind the scenes is that there is a protocol used by the `with` statement. It fetches the object returned by the `open` statement, let's call it "thefile" in this case. - -It _always_ calls the `thefile.__enter__` function before starting the block of code under it and _always_ calls `thefile.__exit__` after finishing the block of code. - -So the code that we would have written in a `finally` block should be taken care of automatically by the `__exit__` method. This is what helps us to avoid having to use explicit `try..finally` statements repeatedly. - -More discussion on this topic is beyond scope of this book, so please refer [PEP 343](http://www.python.org/dev/peps/pep-0343/) for a comprehensive explanation. - -## Summary - -We have discussed the usage of the `try..except` and `try..finally` statements. We have seen how to create our own exception types and how to raise exceptions as well. - -Next, we will explore the Python Standard Library. diff --git a/feedback.md b/feedback.md deleted file mode 100644 index 78c6e059..00000000 --- a/feedback.md +++ /dev/null @@ -1,3 +0,0 @@ -# Feedback - -The book needs the help of its readers such as yourselves to point out any parts of the book which are not good, not comprehensible or are simply wrong. Please [write to the main author]({{ book.contactUrl }}) or the respective [translators](./translations.md#translations) with your comments and suggestions. diff --git a/first_steps.md b/first_steps.md deleted file mode 100644 index 72395d50..00000000 --- a/first_steps.md +++ /dev/null @@ -1,190 +0,0 @@ -# First Steps - -We will now see how to run a traditional 'Hello World' program in Python. This will teach you how to write, save and run Python programs. - -There are two ways of using Python to run your program - using the interactive interpreter prompt or using a source file. We will now see how to use both of these methods. - -## Using The Interpreter Prompt - -Open the terminal in your operating system (as discussed previously in the [Installation](./installation.md#installation) chapter) and then open the Python prompt by typing `python3` and pressing `[enter]` key. - -Once you have started Python, you should see `>>>` where you can start typing stuff. This is called the _Python interpreter prompt_. - -At the Python interpreter prompt, type: - -```python -print("Hello World") -``` - -followed by the `[enter]` key. You should see the words `Hello World` printed to the screen. - -Here is an example of what you should be seeing, when using a Mac OS X computer. The details about the Python software will differ based on your computer, but the part from the prompt (i.e. from `>>>` onwards) should be the same regardless of the operating system. - - -```python -> python3 -Python 3.5.1 (default, Jan 14 2016, 06:54:11) -[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin -Type "help", "copyright", "credits" or "license" for more information. ->>> print("Hello World") -Hello World -``` - -Notice that Python gives you the output of the line immediately! What you just entered is a single Python _statement_. We use `print` to (unsurprisingly) print any value that you supply to it. Here, we are supplying the text `Hello World` and this is promptly printed to the screen. - -### How to Quit the Interpreter Prompt - -If you are using a GNU/Linux or OS X shell, you can exit the interpreter prompt by pressing `[ctrl + d]` or entering `exit()` (note: remember to include the parentheses, `()`) followed by the `[enter]` key. - -If you are using the Windows command prompt, press `[ctrl + z]` followed by the `[enter]` key. - -## Choosing An Editor - -We cannot type out our program at the interpreter prompt every time we want to run something, so we have to save them in files and can run our programs any number of times. - -To create our Python source files, we need an editor software where you can type and save. A good programmer's editor will make your life easier in writing the source files. Hence, the choice of an editor is crucial indeed. You have to choose an editor as you would choose a car you would buy. A good editor will help you write Python programs easily, making your journey more comfortable and helps you reach your destination (achieve your goal) in a much faster and safer way. - -One of the very basic requirements is _syntax highlighting_ where all the different parts of your Python program are colorized so that you can _see_ your program and visualize its running. - -If you have no idea where to start, I would recommend using [PyCharm Educational Edition](https://www.jetbrains.com/pycharm-edu/) software which is available on Windows, Mac OS X and GNU/Linux. Details in the next section. - -If you are using Windows, *do not use Notepad* - it is a bad choice because it does not do syntax highlighting and also importantly it does not support indentation of the text which is very important in our case as we will see later. Good editors will automatically do this. - -If you are an experienced programmer, then you must be already using [Vim](http://www.vim.org) or [Emacs](http://www.gnu.org/software/emacs/). Needless to say, these are two of the most powerful editors and you will benefit from using them to write your Python programs. I personally use both for most of my programs, and have even written an [entire book on Vim]({{ book.vimBookUrl }}). - -In case you are willing to take the time to learn Vim or Emacs, then I highly recommend that you do learn to use either of them as it will be very useful for you in the long run. However, as I mentioned before, beginners can start with PyCharm and focus the learning on Python rather than the editor at this moment. - -To reiterate, please choose a proper editor - it can make writing Python programs more fun and easy. - -## PyCharm {#pycharm} - -[PyCharm Educational Edition](https://www.jetbrains.com/pycharm-edu/) is a free editor which you can use for writing Python programs. - -When you open PyCharm, you'll see this, click on `Create New Project`: - -![When you open PyCharm](./img/pycharm_open.png) - -Select `Pure Python`: - -![PyCharm New Project](./img/pycharm_create_new_project.png) - -Change `untitled` to `helloworld` as the location of the project, you should see details similar to this: - -![PyCharm project details](./img/pycharm_create_new_project_pure_python.png) - -Click the `Create` button. - -Right-click on the `helloworld` in the sidebar and select `New` -> `Python File`: - -![PyCharm -> New -> Python File](./img/pycharm_new_python_file.png) - -You will be asked to type the name, type `hello`: - -![PyCharm New File dialog box](./img/pycharm_new_file_input.png) - -You can now see a file opened for you: - -![PyCharm hello.py file](./img/pycharm_hello_open.png) - -Delete the lines that are already present, and now type the following: - - - -```python -print("hello world") -``` -Now right-click on what you typed (without selecting the text), and click on `Run 'hello'`. - -![PyCharm Run 'hello'](./img/pycharm_run.png) - -You should now see the output (what it prints) of your program: - -![PyCharm output](./img/pycharm_output.png) - -Phew! That was quite a few steps to get started, but henceforth, every time we ask you to create a new file, remember to just right-click on `helloworld` on the left -> `New` -> `Python File` and continue the same steps to type and run as shown above. - -You can find more information about PyCharm in the [PyCharm Quickstart](https://www.jetbrains.com/pycharm-educational/quickstart/) page. - -## Vim - -1. Install [Vim](http://www.vim.org) - * Mac OS X users should install `macvim` package via [HomeBrew](http://brew.sh/) - * Windows users should download the "self-installing executable" from [Vim website](http://www.vim.org/download.php) - * GNU/Linux users should get Vim from their distribution's software repositories, e.g. Debian and Ubuntu users can install the `vim` package. -2. Install [jedi-vim](https://github.com/davidhalter/jedi-vim) plugin for autocompletion. -3. Install corresponding `jedi` python package : `pip install -U jedi` - -## Emacs - -1. Install [Emacs 24+](http://www.gnu.org/software/emacs/). - * Mac OS X users should get Emacs from http://emacsformacosx.com - * Windows users should get Emacs from http://ftp.gnu.org/gnu/emacs/windows/ - * GNU/Linux users should get Emacs from their distribution's software repositories, e.g. Debian and Ubuntu users can install the `emacs24` package. -2. Install [ELPY](https://github.com/jorgenschaefer/elpy/wiki) - -## Using A Source File - -Now let's get back to programming. There is a tradition that whenever you learn a new programming language, the first program that you write and run is the 'Hello World' program - all it does is just say 'Hello World' when you run it. As Simon Cozens[^1] says, it is the "traditional incantation to the programming gods to help you learn the language better." - -Start your choice of editor, enter the following program and save it as `hello.py`. - -If you are using PyCharm, we have already [discussed how to run from a source file](#pycharm). - -For other editors, open a new file `hello.py` and type this: - -```python -print("hello world") -``` - -Where should you save the file? To any folder for which you know the location of the folder. If you -don't understand what that means, create a new folder and use that location to save and run all -your Python programs: - -- `/tmp/py` on Mac OS X -- `/tmp/py` on GNU/Linux -- `C:\\py` on Windows - -To create the above folder (for the operating system you are using), use the `mkdir` command in the terminal, for example, `mkdir /tmp/py`. - -IMPORTANT: Always ensure that you give it the file extension of `.py`, for example, `foo.py`. - -To run your Python program: - -1. Open a terminal window (see the previous [Installation](./installation.md#installation) chapter on how to do that) -2. **C**hange **d**irectory to where you saved the file, for example, `cd /tmp/py` -3. Run the program by entering the command `python hello.py`. The output is as shown below. - -``` -$ python hello.py -hello world -``` - -![Screenshot of running program in terminal](./img/terminal_screenshot.png) - -If you got the output as shown above, congratulations! - you have successfully run your first Python program. You have successfully crossed the hardest part of learning programming, which is, getting started with your first program! - -In case you got an error, please type the above program _exactly_ as shown above and run the program again. Note that Python is case-sensitive i.e. `print` is not the same as `Print` - note the lowercase `p` in the former and the uppercase `P` in the latter. Also, ensure there are no spaces or tabs before the first character in each line - we will see [why this is important](./basics.md#indentation) later. - -**How It Works** - -A Python program is composed of _statements_. In our first program, we have only one statement. In this statement, we call the `print` _statement_ to which we supply the text "hello world". - -## Getting Help - -If you need quick information about any function or statement in Python, then you can use the built-in `help` functionality. This is very useful especially when using the interpreter prompt. For example, run `help('len')` - this displays the help for the `len` function which is used to count number of items. - -TIP: Press `q` to exit the help. - -Similarly, you can obtain information about almost anything in Python. Use `help()` to learn more about using `help` itself! - -In case you need to get help for operators like `return`, then you need to put those inside quotes such as `help('return')` so that Python doesn't get confused on what we're trying to do. - -## Summary - -You should now be able to write, save and run Python programs at ease. - -Now that you are a Python user, let's learn some more Python concepts. - ---- - -[^1]: the author of the amazing 'Beginning Perl' book diff --git a/floss.md b/floss.md deleted file mode 100644 index 5ead80ea..00000000 --- a/floss.md +++ /dev/null @@ -1,41 +0,0 @@ -# Appendix: FLOSS {#floss} - -> NOTE: Please note that this section was written in 2003, so some of this will sound quaint to you :-) - -"Free/Libre and Open Source Software", in short, [FLOSS](http://en.wikipedia.org/wiki/FLOSS) is based on the concept of a community, which itself is based on the concept of sharing, and particularly the sharing of knowledge. FLOSS are free for usage, modification and redistribution. - -If you have already read this book, then you are already familiar with FLOSS since you have been using *Python* all along and Python is an open source software! - -Here are some examples of FLOSS to give an idea of the kind of things that community sharing and building can create: - -[Linux](http://www.kernel.org): This is a FLOSS OS kernel used in the GNU/Linux operating system. Linux, the kernel, was started by Linus Torvalds as a student. Android is based on Linux. Any website you use these days will mostly be running on Linux. - -[Ubuntu](http://www.ubuntu.com): This is a community-driven distribution, sponsored by Canonical and it is the most popular GNU/Linux distribution today. It allows you to install a plethora of FLOSS available and all this in an easy-to-use and easy-to-install manner. Best of all, you can just reboot your computer and run GNU/Linux off the CD! This allows you to completely try out the new OS before installing it on your computer. However, Ubuntu is not entirely free software; it contains proprietary drivers, firmware, and applications. - -[LibreOffice](http://www.libreoffice.org/): This is an excellent community-driven and developed office suite with a writer, presentation, spreadsheet and drawing components among other things. It can even open and edit MS Word and MS PowerPoint files with ease. It runs on almost all platforms and is entirely free, libre and open source software. - -[Mozilla Firefox](http://www.mozilla.org/products/firefox): This is _the_ best web browser. It is blazingly fast and has gained critical acclaim for its sensible and impressive features. The extensions concept allows any kind of plugins to be used. - -[Mono](http://www.mono-project.com): This is an open source implementation of the Microsoft .NET platform. It allows .NET applications to be created and run on GNU/Linux, Windows, FreeBSD, Mac OS and many other platforms as well. - -[Apache web server](http://httpd.apache.org): This is the popular open source web server. In fact, it is _the_ most popular web server on the planet! It runs nearly more than half of the websites out there. Yes, that's right - Apache handles more websites than all the competition (including Microsoft IIS) combined. - -[VLC Player](http://www.videolan.org/vlc/): This is a video player that can play anything from DivX to MP3 to Ogg to VCDs and DVDs to ... who says open source ain't fun? ;-) - -This list is just intended to give you a brief idea - there are many more excellent FLOSS out there, such as the Perl language, PHP language, Drupal content management system for websites, PostgreSQL database server, TORCS racing game, KDevelop IDE, Xine - the movie player, VIM editor, Quanta+ editor, Banshee audio player, GIMP image editing program, ... This list could go on forever. - -To get the latest buzz in the FLOSS world, check out the following websites: - -- [OMG! Ubuntu!](http://www.omgubuntu.co.uk/) -- [Web Upd8](http://www.webupd8.org/) -- [DistroWatch](http://www.distrowatch.com) -- [Planet Debian](http://planet.debian.org/) - -Visit the following websites for more information on FLOSS: - -- [GitHub Explore](http://github.com/explore) -- [Code Triage](http://www.codetriage.com/) -- [SourceForge](http://www.sourceforge.net) -- [FreshMeat](http://www.freshmeat.net) - -So, go ahead and explore the vast, free and open world of FLOSS! diff --git a/functions.md b/functions.md deleted file mode 100644 index 6b3e9440..00000000 --- a/functions.md +++ /dev/null @@ -1,217 +0,0 @@ -# Functions - -Functions are reusable pieces of programs. They allow you to give a name to a block of statements, allowing you to run that block using the specified name anywhere in your program and any number of times. This is known as *calling* the function. We have already used many built-in functions such as `len` and `range`. - -The function concept is probably *the* most important building block of any non-trivial software (in any programming language), so we will explore various aspects of functions in this chapter. - -Functions are defined using the `def` keyword. After this keyword comes an *identifier* name for the function, followed by a pair of parentheses which may enclose some names of variables, and by the final colon that ends the line. Next follows the block of statements that are part of this function. An example will show that this is actually very simple: - -Example (save as `function1.py`): - -
{% include "./programs/function1.py" %}
- -Output: - -
{% include "./programs/function1.txt" %}
- -**How It Works** - -We define a function called `say_hello` using the syntax as explained above. This function takes no parameters and hence there are no variables declared in the parentheses. Parameters to functions are just input to the function so that we can pass in different values to it and get back corresponding results. - -Notice that we can call the same function twice which means we do not have to write the same code again. - -## Function Parameters - -A function can take parameters, which are values you supply to the function so that the function -can *do* something utilising those values. These parameters are just like variables except that the -values of these variables are defined when we call the function and are already assigned values -when the function runs. - -Parameters are specified within the pair of parentheses in the function definition, separated by -commas. When we call the function, we supply the values in the same way. Note the terminology -used - the names given in the function definition are called *parameters* whereas the values you -supply in the function call are called *arguments*. - -Example (save as `function_param.py`): - -
{% include "./programs/function_param.py" %}
- -Output: - -
{% include "./programs/function_param.txt" %}
- -**How It Works** - -Here, we define a function called `print_max` that uses two parameters called `a` and `b`. We find out the greater number using a simple `if..else` statement and then print the bigger number. - -The first time we call the function `print_max`, we directly supply the numbers as arguments. In the second case, we call the function with variables as arguments. `print_max(x, y)` causes the value of argument `x` to be assigned to parameter `a` and the value of argument `y` to be assigned to parameter `b`. The `print_max` function works the same way in both cases. - -## Local Variables - -When you declare variables inside a function definition, they are not related in any way to other variables with the same names used outside the function - i.e. variable names are *local* to the function. This is called the *scope* of the variable. All variables have the scope of the block they are declared in starting from the point of definition of the name. - -Example (save as `function_local.py`): - -
{% include "./programs/function_local.py" %}
- -Output: - -
{% include "./programs/function_local.txt" %}
- -**How It Works** - -The first time that we print the *value* of the name *x* with the first line in the function's body, Python uses the value of the parameter declared in the main block, above the function definition. - -Next, we assign the value `2` to `x`. The name `x` is local to our function. So, when we change the value of `x` in the function, the `x` defined in the main block remains unaffected. - -With the last `print` statement, we display the value of `x` as defined in the main block, thereby confirming that it is actually unaffected by the local assignment within the previously called function. - -## The `global` statement {#global-statement} - -If you want to assign a value to a name defined at the top level of the program (i.e. not inside any kind of scope such as functions or classes), then you have to tell Python that the name is not local, but it is *global*. We do this using the `global` statement. It is impossible to assign a value to a variable defined outside a function without the `global` statement. - -You can use the values of such variables defined outside the function (assuming there is no variable with the same name within the function). However, this is not encouraged and should be avoided since it becomes unclear to the reader of the program as to where that variable's definition is. Using the `global` statement makes it amply clear that the variable is defined in an outermost block. - -Example (save as `function_global.py`): - -
{% include "./programs/function_global.py" %}
- -Output: - -
{% include "./programs/function_global.txt" %}
- -**How It Works** - -The `global` statement is used to declare that `x` is a global variable - hence, when we assign a value to `x` inside the function, that change is reflected when we use the value of `x` in the main block. - -You can specify more than one global variable using the same `global` statement e.g. `global x, y, z`. - -## Default Argument Values {#default-arguments} - -For some functions, you may want to make some parameters *optional* and use default values in case the user does not want to provide values for them. This is done with the help of default argument values. You can specify default argument values for parameters by appending to the parameter name in the function definition the assignment operator (`=`) followed by the default value. - -Note that the default argument value should be a constant. More precisely, the default argument value should be immutable - this is explained in detail in later chapters. For now, just remember this. - -Example (save as `function_default.py`): - -
{% include "./programs/function_default.py" %}
- -Output: - -
{% include "./programs/function_default.txt" %}
- -**How It Works** - -The function named `say` is used to print a string as many times as specified. If we don't supply a value, then by default, the string is printed just once. We achieve this by specifying a default argument value of `1` to the parameter `times`. - -In the first usage of `say`, we supply only the string and it prints the string once. In the second usage of `say`, we supply both the string and an argument `5` stating that we want to *say* the string message 5 times. - -> *CAUTION* -> -> Only those parameters which are at the end of the parameter list can be given default argument -> values i.e. you cannot have a parameter with a default argument value preceding a parameter without -> a default argument value in the function's parameter list. -> -> This is because the values are assigned to the parameters by position. For example,`def func(a, -> b=5)` is valid, but `def func(a=5, b)` is *not valid*. - -## Keyword Arguments - -If you have some functions with many parameters and you want to specify only some of them, then you can give values for such parameters by naming them - this is called *keyword arguments* - we use the name (keyword) instead of the position (which we have been using all along) to specify the arguments to the function. - -There are two advantages - one, using the function is easier since we do not need to worry about the order of the arguments. Two, we can give values to only those parameters to which we want to, provided that the other parameters have default argument values. - -Example (save as `function_keyword.py`): - -
{% include "./programs/function_keyword.py" %}
- -Output: - -
{% include "./programs/function_keyword.txt" %}
- -**How It Works** - -The function named `func` has one parameter without a default argument value, followed by two parameters with default argument values. - -In the first usage, `func(3, 7)`, the parameter `a` gets the value `3`, the parameter `b` gets the value `7` and `c` gets the default value of `10`. - -In the second usage `func(25, c=24)`, the variable `a` gets the value of 25 due to the position of the argument. Then, the parameter `c` gets the value of `24` due to naming i.e. keyword arguments. The variable `b` gets the default value of `5`. - -In the third usage `func(c=50, a=100)`, we use keyword arguments for all specified values. Notice that we are specifying the value for parameter `c` before that for `a` even though `a` is defined before `c` in the function definition. - -## VarArgs parameters - -Sometimes you might want to define a function that can take _any_ number of parameters, i.e. **var**iable number of **arg**uments, this can be achieved by using the stars (save as `function_varargs.py`): - -
{% include "./programs/function_varargs.py" %}
- -Output: - -
{% include "./programs/function_varargs.txt" %}
- -**How It Works** - -When we declare a starred parameter such as `*param`, then all the positional arguments from that point till the end are collected as a tuple called 'param'. - -Similarly, when we declare a double-starred parameter such as `**param`, then all the keyword arguments from that point till the end are collected as a dictionary called 'param'. - -We will explore tuples and dictionaries in a [later chapter](./data_structures.md#data-structures). - -## The `return` statement {#return-statement} - -The `return` statement is used to *return* from a function i.e. break out of the function. We can optionally *return a value* from the function as well. - -Example (save as `function_return.py`): - -
{% include "./programs/function_return.py" %}
- -Output: - -
{% include "./programs/function_return.txt" %}
- -**How It Works** - -The `maximum` function returns the maximum of the parameters, in this case the numbers supplied to the function. It uses a simple `if..else` statement to find the greater value and then *returns* that value. - -Note that a `return` statement without a value is equivalent to `return None`. `None` is a special type in Python that represents nothingness. For example, it is used to indicate that a variable has no value if it has a value of `None`. - -Every function implicitly contains a `return None` statement at the end unless you have written your own `return` statement. You can see this by running `print(some_function())` where the function `some_function` does not use the `return` statement such as: - -```python -def some_function(): - pass -``` - -The `pass` statement is used in Python to indicate an empty block of statements. - -> TIP: There is a built-in function called `max` that already implements the 'find maximum' functionality, so use this built-in function whenever possible. - -## DocStrings - -Python has a nifty feature called *documentation strings*, usually referred to by its shorter name *docstrings*. DocStrings are an important tool that you should make use of since it helps to document the program better and makes it easier to understand. Amazingly, we can even get the docstring back from, say a function, when the program is actually running! - -Example (save as `function_docstring.py`): - -
{% include "./programs/function_docstring.py" %}
- -Output: - -
{% include "./programs/function_docstring.txt" %}
- -**How It Works** - -A string on the first logical line of a function is the *docstring* for that function. Note that DocStrings also apply to [modules](./modules.md#modules) and [classes](./oop.md#oop) which we will learn about in the respective chapters. - -The convention followed for a docstring is a multi-line string where the first line starts with a capital letter and ends with a dot. Then the second line is blank followed by any detailed explanation starting from the third line. You are *strongly advised* to follow this convention for all your docstrings for all your non-trivial functions. - -We can access the docstring of the `print_max` function using the `__doc__` (notice the *double underscores*) attribute (name belonging to) of the function. Just remember that Python treats *everything* as an object and this includes functions. We'll learn more about objects in the chapter on [classes](./oop.md#oop). - -If you have used `help()` in Python, then you have already seen the usage of docstrings! What it does is just fetch the `__doc__` attribute of that function and displays it in a neat manner for you. You can try it out on the function above - just include `help(print_max)` in your program. Remember to press the `q` key to exit `help`. - -Automated tools can retrieve the documentation from your program in this manner. Therefore, I *strongly recommend* that you use docstrings for any non-trivial function that you write. The `pydoc` command that comes with your Python distribution works similarly to `help()` using docstrings. - -## Summary - -We have seen so many aspects of functions but note that we still haven't covered all aspects of them. However, we have already covered most of what you'll use regarding Python functions on an everyday basis. - -Next, we will see how to use as well as create Python modules. diff --git a/img/pycharm_command_line_arguments.png b/img/pycharm_command_line_arguments.png index c8175ba3..5d6f6f55 100644 Binary files a/img/pycharm_command_line_arguments.png and b/img/pycharm_command_line_arguments.png differ diff --git a/img/pycharm_create_new_project.png b/img/pycharm_create_new_project.png index 57790c29..d7b80d57 100644 Binary files a/img/pycharm_create_new_project.png and b/img/pycharm_create_new_project.png differ diff --git a/img/pycharm_create_new_project_pure_python.png b/img/pycharm_create_new_project_pure_python.png index 2a63f2e3..cb02b013 100644 Binary files a/img/pycharm_create_new_project_pure_python.png and b/img/pycharm_create_new_project_pure_python.png differ diff --git a/img/pycharm_hello_open.png b/img/pycharm_hello_open.png index edea2ec7..654598cf 100644 Binary files a/img/pycharm_hello_open.png and b/img/pycharm_hello_open.png differ diff --git a/img/pycharm_new_file_input.png b/img/pycharm_new_file_input.png index e20c96f2..544f1adc 100644 Binary files a/img/pycharm_new_file_input.png and b/img/pycharm_new_file_input.png differ diff --git a/img/pycharm_new_python_file.png b/img/pycharm_new_python_file.png index 9a3cc272..7937d0d5 100644 Binary files a/img/pycharm_new_python_file.png and b/img/pycharm_new_python_file.png differ diff --git a/img/pycharm_open.png b/img/pycharm_open.png index ecc829da..9ee244f6 100644 Binary files a/img/pycharm_open.png and b/img/pycharm_open.png differ diff --git a/img/pycharm_output.png b/img/pycharm_output.png index 9cc793b9..5469204b 100644 Binary files a/img/pycharm_output.png and b/img/pycharm_output.png differ diff --git a/img/pycharm_run.png b/img/pycharm_run.png index 63c7434d..5a6d6ab3 100644 Binary files a/img/pycharm_run.png and b/img/pycharm_run.png differ diff --git a/img/terminal_screenshot.png b/img/terminal_screenshot.png index d3c3107f..414d1ff7 100644 Binary files a/img/terminal_screenshot.png and b/img/terminal_screenshot.png differ diff --git a/installation.md b/installation.md deleted file mode 100644 index 7467f5c5..00000000 --- a/installation.md +++ /dev/null @@ -1,84 +0,0 @@ -# Installation {#installation} - -When we refer to "Python 3" in this book, we will be referring to any version of Python equal to or greater than version [Python {{ book.pythonVersion }}](https://www.python.org/downloads/). - -## Installation on Windows - -Visit https://www.python.org/downloads/ and download the latest version. At the time of this writing, it was Python 3.5.1 -The installation is just like any other Windows-based software. - -CAUTION: Make sure you check option `Add Python 3.5 to PATH`. - -To change install location, click on `Customize installation`, then `Next` and enter `C:\python35` as install location. - -If not checked, check `Add Python to environment variables`. This does the same thing as `Add Python 3.5 to PATH` on the first install screen. - -You can choose to install Launcher for all users or not, it does not matter much. Launcher is used to switch between different versions of Python installed. - -If your path was not set correctly, then follow these steps to fix it. Otherwise, go to `Running Python prompt on Windows`. - -NOTE: For people who already know programming, if you are familiar with Docker, check out [Python in Docker](https://hub.docker.com/_/python/) and [Docker on Windows](https://docs.docker.com/windows/). - -### DOS Prompt {#dos-prompt} - -If you want to be able to use Python from the Windows command line i.e. the DOS prompt, then you need to set the PATH variable appropriately. - -For Windows 2000, XP, 2003 , click on `Control Panel` -> `System` -> `Advanced` -> `Environment Variables`. Click on the variable named `PATH` in the _System Variables_ section, then select `Edit` and add `;C:\Python35` (please verify that this folder exists, it will be different for newer versions of Python) to the end of what is already there. Of course, use the appropriate directory name. - - -For older versions of Windows, open the file `C:\AUTOEXEC.BAT` and add the line `PATH=%PATH%;C:\Python35` and restart the system. For Windows NT, use the `AUTOEXEC.NT` file. - -For Windows Vista: - -- Click Start and choose `Control Panel` -- Click System, on the right you'll see "View basic information about your computer" -- On the left is a list of tasks, the last of which is `Advanced system settings`. Click that. -- The `Advanced` tab of the `System Properties` dialog box is shown. Click the `Environment Variables` button on the bottom right. -- In the lower box titled `System Variables` scroll down to Path and click the `Edit` button. -- Change your path as need be. -- Restart your system. Vista didn't pick up the system path environment variable change until I restarted. - -For Windows 7 and 8: - -- Right click on Computer from your desktop and select `Properties` or click `Start` and choose `Control Panel` -> `System and Security` -> `System`. Click on `Advanced system settings` on the left and then click on the `Advanced` tab. At the bottom click on `Environment Variables` and under `System variables`, look for the `PATH` variable, select and then press `Edit`. -- Go to the end of the line under Variable value and append `;C:\Python35` (please verify that this folder exists, it will be different for newer versions of Python) to the end of what is already there. Of course, use the appropriate folder name. -- If the value was `%SystemRoot%\system32;` It will now become `%SystemRoot%\system32;C:\Python35` -- Click `OK` and you are done. No restart is required, however you may have to close and reopen the command line. - -### Running Python prompt on Windows - -For Windows users, you can run the interpreter in the command line if you have [set the `PATH` variable appropriately](#dos-prompt). - -To open the terminal in Windows, click the start button and click `Run`. In the dialog box, type `cmd` and press `[enter]` key. - -Then, type `python` and ensure there are no errors. - -## Installation on Mac OS X - -For Mac OS X users, use [Homebrew](http://brew.sh): `brew install python3`. - -To verify, open the terminal by pressing `[Command + Space]` keys (to open Spotlight search), type `Terminal` and press `[enter]` key. Now, run `python3` and ensure there are no errors. - -## Installation on GNU/Linux - -For GNU/Linux users, use your distribution's package manager to install Python 3, e.g. on Debian & Ubuntu: `sudo apt-get update && sudo apt-get install python3`. - -To verify, open the terminal by opening the `Terminal` application or by pressing `Alt + F2` and entering `gnome-terminal`. If that doesn't work, please refer the documentation of your particular GNU/Linux distribution. Now, run `python3` and ensure there are no errors. - -You can see the version of Python on the screen by running: - - -``` -$ python3 -V -Python 3.5.1 -``` - -NOTE: `$` is the prompt of the shell. It will be different for you depending on the settings of the operating system on your computer, hence I will indicate the prompt by just the `$` symbol. - -CAUTION: Output may be different on your computer, depending on the version of Python software installed on your computer. - -## Summary - -From now on, we will assume that you have Python installed on your system. - -Next, we will write our first Python program. diff --git a/io.md b/io.md deleted file mode 100644 index 17da7941..00000000 --- a/io.md +++ /dev/null @@ -1,118 +0,0 @@ -# Input and Output {#io} - -There will be situations where your program has to interact with the user. For example, you would want to take input from the user and then print some results back. We can achieve this using the `input()` function and `print` function respectively. - -For output, we can also use the various methods of the `str` (string) class. For example, you can use the `rjust` method to get a string which is right justified to a specified width. See `help(str)` for more details. - -Another common type of input/output is dealing with files. The ability to create, read and write files is essential to many programs and we will explore this aspect in this chapter. - -## Input from user - -Save this program as `io_input.py`: - -
{% include "./programs/io_input.py" %}
- -Output: - -
{% include "./programs/io_input.txt" %}
- -**How It Works** - -We use the slicing feature to reverse the text. We've already seen how we can make [slices from sequences](./data_structures.md#sequence) using the `seq[a:b]` code starting from position `a` to position `b`. We can also provide a third argument that determines the _step_ by which the slicing is done. The default step is `1` because of which it returns a continuous part of the text. Giving a negative step, i.e., `-1` will return the text in reverse. - -The `input()` function takes a string as argument and displays it to the user. Then it waits for the user to type something and press the return key. Once the user has entered and pressed the return key, the `input()` function will then return that text the user has entered. - -We take that text and reverse it. If the original text and reversed text are equal, then the text is a [palindrome](http://en.wiktionary.org/wiki/palindrome). - -### Homework exercise - -Checking whether a text is a palindrome should also ignore punctuation, spaces and case. For example, "Rise to vote, sir." is also a palindrome but our current program doesn't say it is. Can you improve the above program to recognize this palindrome? - -If you need a hint, the idea is that...[^1] - -## Files - -You can open and use files for reading or writing by creating an object of the `file` class and using its `read`, `readline` or `write` methods appropriately to read from or write to the file. The ability to read or write to the file depends on the mode you have specified for the file opening. Then finally, when you are finished with the file, you call the `close` method to tell Python that we are done using the file. - -Example (save as `io_using_file.py`): - -
{% include "./programs/io_using_file.py" %}
- -Output: - -
{% include "./programs/io_using_file.txt" %}
- -**How It Works** - -First, open a file by using the built-in `open` function and specifying the name of the file and the mode in which we want to open the file. The mode can be a read mode (`'r'`), write mode (`'w'`) or append mode (`'a'`). We can also specify whether we are reading, writing, or appending in text mode (`'t'`) or binary mode (`'b'`). There are actually many more modes available and `help(open)` will give you more details about them. By default, `open()` considers the file to be a 't'ext file and opens it in 'r'ead mode. - -In our example, we first open the file in write text mode and use the `write` method of the file object to write to the file and then we finally `close` the file. - -Next, we open the same file again for reading. We don't need to specify a mode because 'read text file' is the default mode. We read in each line of the file using the `readline` method in a loop. This method returns a complete line including the newline character at the end of the line. When an _empty_ string is returned, it means that we have reached the end of the file and we 'break' out of the loop. - -In the end, we finally `close` the file. - -Now, check the contents of the `poem.txt` file to confirm that the program has indeed written to and read from that file. - -## Pickle - -Python provides a standard module called `pickle` using which you can store _any_ plain Python object in a file and then get it back later. This is called storing the object *persistently*. - -Example (save as `io_pickle.py`): - -
{% include "./programs/io_pickle.py" %}
- -Output: - -
{% include "./programs/io_pickle.txt" %}
- -**How It Works** - -To store an object in a file, we have to first `open` the file in __w__rite __b__inary mode and then call the `dump` function of the `pickle` module. This process is called _pickling_. - -Next, we retrieve the object using the `load` function of the `pickle` module which returns the object. This process is called _unpickling_. - -## Unicode - -So far, when we have been writing and using strings, or reading and writing to a file, we have used simple English characters only. - -> NOTE: If you are using Python 2, and we want to be able to read and write other non-English languages, we need to use the `unicode` type, and it all starts with the character `u`, e.g. `u"hello world"` - -```python ->>> "hello world" -'hello world' ->>> type("hello world") - ->>> u"hello world" -'hello world' ->>> type(u"hello world") - -``` - -When we read or write to a file or when we talk to other computers on the Internet, we need to convert our unicode strings into a format that can be sent and received, and that format is called "UTF-8". We can read and write in that format, using a simple keyword argument to our standard `open` function: - -
{% include "./programs/io_unicode.py" %}
- -**How It Works** - -You can ignore the `import` statement for now, we'll explore that in detail in the [modules chapter](./modules.md#modules). - -Whenever we write a program that uses Unicode literals like we have used above, we have to make sure that Python itself is told that our program uses UTF-8, and we have to put `# encoding=utf-8` comment at the top of our program. - -We use `io.open` and provide the "encoding" and "decoding" argument to tell Python that we are using unicode. - -You should learn more about this topic by reading: - -- ["The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets"](http://www.joelonsoftware.com/articles/Unicode.html) -- [Python Unicode Howto](http://docs.python.org/3/howto/unicode.html) -- [Pragmatic Unicode talk by Nat Batchelder](http://nedbatchelder.com/text/unipain.html) - -## Summary - -We have discussed various types of input/output, about file handling, about the pickle module and about Unicode. - -Next, we will explore the concept of exceptions. - ---- - -[^1]: Use a tuple (you can find a list of _all_ [punctuation marks here](http://grammar.ccc.commnet.edu/grammar/marks/marks.htm)) to hold all the forbidden characters, then use the membership test to determine whether a character should be removed or not, i.e. forbidden = (`!`, `?`, `.`, ...). diff --git a/modules.md b/modules.md deleted file mode 100644 index 01e4df5e..00000000 --- a/modules.md +++ /dev/null @@ -1,212 +0,0 @@ -# Modules - -You have seen how you can reuse code in your program by defining functions once. What if you wanted to reuse a number of functions in other programs that you write? As you might have guessed, the answer is modules. - -There are various methods of writing modules, but the simplest way is to create a file with a `.py` extension that contains functions and variables. - -Another method is to write the modules in the native language in which the Python interpreter itself was written. For example, you can write modules in the [C programming language](http://docs.python.org/3/extending/) and when compiled, they can be used from your Python code when using the standard Python interpreter. - -A module can be *imported* by another program to make use of its functionality. This is how we can use the Python standard library as well. First, we will see how to use the standard library modules. - -Example (save as `module_using_sys.py`): - -
{% include "./programs/module_using_sys.py" %}
- -Output: - -
{% include "./programs/module_using_sys.txt" %}
- -**How It Works** - -First, we *import* the `sys` module using the `import` statement. Basically, this translates to us telling Python that we want to use this module. The `sys` module contains functionality related to the Python interpreter and its environment i.e. the **sys**tem. - -When Python executes the `import sys` statement, it looks for the `sys` module. In this case, it is one of the built-in modules, and hence Python knows where to find it. - -If it was not a compiled module i.e. a module written in Python, then the Python interpreter will search for it in the directories listed in its `sys.path` variable. If the module is found, then the statements in the body of that module are run and the module is made *available* for you to use. Note that the initialization is done only the *first* time that we import a module. - -The `argv` variable in the `sys` module is accessed using the dotted notation i.e. `sys.argv`. It clearly indicates that this name is part of the `sys` module. Another advantage of this approach is that the name does not clash with any `argv` variable used in your program. - -The `sys.argv` variable is a *list* of strings (lists are explained in detail in a [later chapter](./data_structures.md#data-structures). Specifically, the `sys.argv` contains the list of *command line arguments* i.e. the arguments passed to your program using the command line. - -If you are using an IDE to write and run these programs, look for a way to specify command line arguments to the program in the menus. - -Here, when we execute `python module_using_sys.py we are arguments`, we run the module `module_using_sys.py` with the `python` command and the other things that follow are arguments passed to the program. Python stores the command line arguments in the `sys.argv` variable for us to use. - -Remember, the name of the script running is always the first element in the `sys.argv` list. So, in this case we will have `'module_using_sys.py'` as `sys.argv[0]`, `'we'` as `sys.argv[1]`, `'are'` as `sys.argv[2]` and `'arguments'` as `sys.argv[3]`. Notice that Python starts counting from 0 and not 1. - -The `sys.path` contains the list of directory names where modules are imported from. Observe that the first string in `sys.path` is empty - this empty string indicates that the current directory is also part of the `sys.path` which is same as the `PYTHONPATH` environment variable. This means that you can directly import modules located in the current directory. Otherwise, you will have to place your module in one of the directories listed in `sys.path`. - -Note that the current directory is the directory from which the program is launched. Run `import os; print(os.getcwd())` to find out the current directory of your program. - -## Byte-compiled .pyc files {#pyc} - -Importing a module is a relatively costly affair, so Python does some tricks to make it faster. One way is to create *byte-compiled* files with the extension `.pyc` which is an intermediate form that Python transforms the program into (remember the [introduction section](./about_python.md#interpreted) on how Python works?). This `.pyc` file is useful when you import the module the next time from a different program - it will be much faster since a portion of the processing required in importing a module is already done. Also, these byte-compiled files are platform-independent. - -NOTE: These `.pyc` files are usually created in the same directory as the corresponding `.py` files. If Python does not have permission to write to files in that directory, then the `.pyc` files will _not_ be created. - -## The from..import statement {#from-import-statement} - -If you want to directly import the `argv` variable into your program (to avoid typing the `sys.` everytime for it), then you can use the `from sys import argv` statement. - -> WARNING: In general, *avoid* using the `from..import` statement, use the `import` statement instead. This is because your program will avoid name clashes and will be more readable. - -Example: - -```python -from math import sqrt -print("Square root of 16 is", sqrt(16)) -``` - -## A module's `__name__` {#module-name} - -Every module has a name and statements in a module can find out the name of their module. This is handy for the particular purpose of figuring out whether the module is being run standalone or being imported. As mentioned previously, when a module is imported for the first time, the code it contains gets executed. We can use this to make the module behave in different ways depending on whether it is being used by itself or being imported from another module. This can be achieved using the `__name__` attribute of the module. - -Example (save as `module_using_name.py`): - -
{% include "./programs/module_using_name.py" %}
- -Output: - -
{% include "./programs/module_using_name.txt" %}
- -**How It Works** - -Every Python module has its `__name__` defined. If this is `'__main__'`, that implies that the module is being run standalone by the user and we can take appropriate actions. - -## Making Your Own Modules - -Creating your own modules is easy, you've been doing it all along! This is because every Python program is also a module. You just have to make sure it has a `.py` extension. The following example should make it clear. - -Example (save as `mymodule.py`): - -
{% include "./programs/mymodule.py" %}
- -The above was a sample *module*. As you can see, there is nothing particularly special about it compared to our usual Python program. We will next see how to use this module in our other Python programs. - -Remember that the module should be placed either in the same directory as the program from which we import it, or in one of the directories listed in `sys.path`. - -Another module (save as `mymodule_demo.py`): - -
{% include "./programs/mymodule_demo.py" %}
- -Output: - -
{% include "./programs/mymodule_demo.txt" %}
- -**How It Works** - -Notice that we use the same dotted notation to access members of the module. Python makes good reuse of the same notation to give the distinctive 'Pythonic' feel to it so that we don't have to keep learning new ways to do things. - -Here is a version utilising the `from..import` syntax (save as `mymodule_demo2.py`): - -
{% include "./programs/mymodule_demo2.py" %}
- -The output of `mymodule_demo2.py` is same as the output of `mymodule_demo.py`. - -Notice that if there was already a `__version__` name declared in the module that imports mymodule, there would be a clash. This is also likely because it is common practice for each module to declare it's version number using this name. Hence, it is always recommended to prefer the `import` statement even though it might make your program a little longer. - -You could also use: - -```python -from mymodule import * -``` - -This will import all public names such as `say_hi` but would not import `__version__` because it starts with double underscores. - -> WARNING: Remember that you should avoid using import-star, i.e. `from mymodule import *`. - - - -> **Zen of Python** -> -> One of Python's guiding principles is that "Explicit is better than Implicit". Run `import this` in Python to learn more. - -## The `dir` function {#dir-function} - -Built-in `dir()` function returns list of names defined by an object. -If the object is a module, this list includes functions, classes and variables, defined inside that module. - -This function can accept arguments. -If the argument is the name of the module, function returns list of names from that specified module. -If there is no argument, function returns list of names from the current module. - -Example: - -```python -$ python ->>> import sys - -# get names of attributes in sys module ->>> dir(sys) -['__displayhook__', '__doc__', -'argv', 'builtin_module_names', -'version', 'version_info'] -# only few entries shown here - -# get names of attributes for current module ->>> dir() -['__builtins__', '__doc__', -'__name__', '__package__'] - -# create a new variable 'a' ->>> a = 5 - ->>> dir() -['__builtins__', '__doc__', '__name__', '__package__', 'a'] - -# delete/remove a name ->>> del a - ->>> dir() -['__builtins__', '__doc__', '__name__', '__package__'] -``` - -**How It Works** - -First, we see the usage of `dir` on the imported `sys` module. We can see the huge list of attributes that it contains. - -Next, we use the `dir` function without passing parameters to it. By default, it returns the list of attributes for the current module. Notice that the list of imported modules is also part of this list. - -In order to observe the `dir` in action, we define a new variable `a` and assign it a value and then check `dir` and we observe that there is an additional value in the list of the same name. We remove the variable/attribute of the current module using the `del` statement and the change is reflected again in the output of the `dir` function. - -A note on `del` - this statement is used to *delete* a variable/name and after the statement has run, in this case `del a`, you can no longer access the variable `a` - it is as if it never existed before at all. - -Note that the `dir()` function works on *any* object. For example, run `dir(str)` for the attributes of the `str` (string) class. - -There is also a [`vars()`](http://docs.python.org/3/library/functions.html#vars) function which can potentially give you the attributes and their values, but it will not work for all cases. - -## Packages - -By now, you must have started observing the hierarchy of organizing your programs. Variables usually go inside functions. Functions and global variables usually go inside modules. What if you wanted to organize modules? That's where packages come into the picture. - -Packages are just folders of modules with a special `__init__.py` file that indicates to Python that this folder is special because it contains Python modules. - -Let's say you want to create a package called 'world' with subpackages 'asia', 'africa', etc. and these subpackages in turn contain modules like 'india', 'madagascar', etc. - -This is how you would structure the folders: - -``` -- / - - world/ - - __init__.py - - asia/ - - __init__.py - - india/ - - __init__.py - - foo.py - - africa/ - - __init__.py - - madagascar/ - - __init__.py - - bar.py -``` - -Packages are just a convenience to hierarchically organize modules. You will see many instances of this in the [standard library](./stdlib.md#stdlib). - -## Summary - -Just like functions are reusable parts of programs, modules are reusable programs. Packages are another hierarchy to organize modules. The standard library that comes with Python is an example of such a set of packages and modules. - -We have seen how to use these modules and create our own modules. - -Next, we will learn about some interesting concepts called data structures. diff --git a/more.md b/more.md deleted file mode 100644 index 91552e09..00000000 --- a/more.md +++ /dev/null @@ -1,174 +0,0 @@ -# More - -So far we have covered a majority of the various aspects of Python that you will use. In this chapter, we will cover some more aspects that will make our knowledge of Python more well-rounded. - -## Passing tuples around - -Ever wished you could return two different values from a function? You can. All you have to do is use a tuple. - -```python ->>> def get_error_details(): -... return (2, 'details') -... ->>> errnum, errstr = get_error_details() ->>> errnum -2 ->>> errstr -'details' -``` - -Notice that the usage of `a, b = ` interprets the result of the expression as a tuple with two values. - -This also means the fastest way to swap two variables in Python is: - -```python ->>> a = 5; b = 8 ->>> a, b -(5, 8) ->>> a, b = b, a ->>> a, b -(8, 5) -``` - -## Special Methods - -There are certain methods such as the `__init__` and `__del__` methods which have special significance in classes. - -Special methods are used to mimic certain behaviors of built-in types. For example, if you want to use the `x[key]` indexing operation for your class (just like you use it for lists and tuples), then all you have to do is implement the `__getitem__()` method and your job is done. If you think about it, this is what Python does for the `list` class itself! - -Some useful special methods are listed in the following table. If you want to know about all the special methods, [see the manual](http://docs.python.org/3/reference/datamodel.html#special-method-names). - -- `__init__(self, ...)` - - This method is called just before the newly created object is returned for usage. - -- `__del__(self)` - - Called just before the object is destroyed (which has unpredictable timing, so avoid using this) - -- `__str__(self)` - - Called when we use the `print` function or when `str()` is used. - -- `__lt__(self, other)` - - Called when the _less than_ operator (<) is used. Similarly, there are special methods for all the operators (+, >, etc.) - -- `__getitem__(self, key)` - - Called when `x[key]` indexing operation is used. - -- `__len__(self)` - - Called when the built-in `len()` function is used for the sequence object. - -## Single Statement Blocks - -We have seen that each block of statements is set apart from the rest by its own indentation level. Well, there is one caveat. If your block of statements contains only one single statement, then you can specify it on the same line of, say, a conditional statement or looping statement. The following example should make this clear: - -```python ->>> flag = True ->>> if flag: print('Yes') -... -Yes -``` - -Notice that the single statement is used in-place and not as a separate block. Although, you can use this for making your program _smaller_, I strongly recommend avoiding this short-cut method, except for error checking, mainly because it will be much easier to add an extra statement if you are using proper indentation. - -## Lambda Forms - -A `lambda` statement is used to create new function objects. Essentially, the `lambda` takes a parameter followed by a single expression only which becomes the body of the function and the value of this expression is returned by the new function. - -Example (save as `more_lambda.py`): - -
{% include "./programs/more_lambda.py" %}
- -Output: - -
{% include "./programs/more_lambda.txt" %}
- -**How It Works** - -Notice that the `sort` method of a `list` can take a `key` parameter which determines how the list is sorted (usually we know only about ascending or descending order). In our case, we want to do a custom sort, and for that we need to write a function but instead of writing a separate `def` block for a function that will get used in only this one place, we use a lambda expression to create a new function. - -## List Comprehension - -List comprehensions are used to derive a new list from an existing list. Suppose you have a list of numbers and you want to get a corresponding list with all the numbers multiplied by 2 only when the number itself is greater than 2. List comprehensions are ideal for such situations. - -Example (save as `more_list_comprehension.py`): - -
{% include "./programs/more_list_comprehension.py" %}
- -Output: - -
{% include "./programs/more_list_comprehension.txt" %}
- -**How It Works** - -Here, we derive a new list by specifying the manipulation to be done (`2*i`) when some condition is satisfied (`if i > 2`). Note that the original list remains unmodified. - -The advantage of using list comprehensions is that it reduces the amount of boilerplate code required when we use loops to process each element of a list and store it in a new list. - -## Receiving Tuples and Dictionaries in Functions - -There is a special way of receiving parameters to a function as a tuple or a dictionary using the `*` or `**` prefix respectively. This is useful when taking variable number of arguments in the function. - -```python ->>> def powersum(power, *args): -... '''Return the sum of each argument raised to the specified power.''' -... total = 0 -... for i in args: -... total += pow(i, power) -... return total -... ->>> powersum(2, 3, 4) -25 ->>> powersum(2, 10) -100 -``` - -Because we have a `*` prefix on the `args` variable, all extra arguments passed to the function are stored in `args` as a tuple. If a `**` prefix had been used instead, the extra parameters would be considered to be key/value pairs of a dictionary. - -## The assert statement {#assert} - -The `assert` statement is used to assert that something is true. For example, if you are very sure that you will have at least one element in a list you are using and want to check this, and raise an error if it is not true, then `assert` statement is ideal in this situation. When the assert statement fails, an `AssertionError` is raised. - -```python ->>> mylist = ['item'] ->>> assert len(mylist) >= 1 ->>> mylist.pop() -'item' ->>> assert len(mylist) >= 1 -Traceback (most recent call last): - File "", line 1, in -AssertionError -``` - -The `assert` statement should be used judiciously. Most of the time, it is better to catch exceptions, either handle the problem or display an error message to the user and then quit. - -## Decorators {#decorator} - -Decorators are a shortcut to applying wrapper functions. This is helpful to "wrap" functionality with the same code over and over again. For example, I created a `retry` decorator for myself that I can just apply to any function and if any exception is thrown during a run, it is retried again, till a maximum of 5 times and with a delay between each retry. This is especially useful for situations where you are trying to make a network call to a remote computer: - -
{% include "./programs/more_decorator.py" %}
- -Output: - -
{% include "./programs/more_decorator.txt" %}
- -**How It Works** - -See: - -- http://www.ibm.com/developerworks/linux/library/l-cpdecor.html -- http://toumorokoshi.github.io/dry-principles-through-python-decorators.html - -## Differences between Python 2 and Python 3 {#two-vs-three} - -See: - -- ["Six" library](http://pythonhosted.org/six/) -- [Porting to Python 3 Redux by Armin](http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/) -- [Python 3 experience by PyDanny](http://pydanny.com/experiences-with-django-python3.html) -- [Official Django Guide to Porting to Python 3](https://docs.djangoproject.com/en/dev/topics/python3/) -- [Discussion on What are the advantages to python 3.x?](http://www.reddit.com/r/Python/comments/22ovb3/what_are_the_advantages_to_python_3x/) - -## Summary - -We have covered some more features of Python in this chapter and yet we haven't covered all the features of Python. However, at this stage, we have covered most of what you are ever going to use in practice. This is sufficient for you to get started with whatever programs you are going to create. - -Next, we will discuss how to explore Python further. diff --git a/oop.md b/oop.md deleted file mode 100644 index cb7096d9..00000000 --- a/oop.md +++ /dev/null @@ -1,184 +0,0 @@ -# Object Oriented Programming {#oop} - -In all the programs we wrote till now, we have designed our program around functions i.e. blocks of statements which manipulate data. This is called the _procedure-oriented_ way of programming. There is another way of organizing your program which is to combine data and functionality and wrap it inside something called an object. This is called the _object oriented_ programming paradigm. Most of the time you can use procedural programming, but when writing large programs or have a problem that is better suited to this method, you can use object oriented programming techniques. - -Classes and objects are the two main aspects of object oriented programming. A **class** creates a new _type_ where **objects** are **instances** of the class. An analogy is that you can have variables of type `int` which translates to saying that variables that store integers are variables which are instances (objects) of the `int` class. - -> **Note for Static Language Programmers** -> -> Note that even integers are treated as objects (of the `int` class). This is unlike C++ and Java (before version 1.5) where integers are primitive native types. -> -> See `help(int)` for more details on the class. -> -> C# and Java 1.5 programmers will find this similar to the _boxing and unboxing_ concept. - -Objects can store data using ordinary variables that _belong_ to the object. Variables that belong to an object or class are referred to as **fields**. Objects can also have functionality by using functions that _belong_ to a class. Such functions are called **methods** of the class. This terminology is important because it helps us to differentiate between functions and variables which are independent and those which belong to a class or object. Collectively, the fields and methods can be referred to as the **attributes** of that class. - -Fields are of two types - they can belong to each instance/object of the class or they can belong to the class itself. They are called **instance variables** and **class variables** respectively. - -A class is created using the `class` keyword. The fields and methods of the class are listed in an indented block. - -## The `self` {#self} - -Class methods have only one specific difference from ordinary functions - they must have an extra first name that has to be added to the beginning of the parameter list, but you **do not** give a value for this parameter when you call the method, Python will provide it. This particular variable refers to the object _itself_, and by convention, it is given the name `self`. - -Although, you can give any name for this parameter, it is _strongly recommended_ that you use the name `self` - any other name is definitely frowned upon. There are many advantages to using a standard name - any reader of your program will immediately recognize it and even specialized IDEs (Integrated Development Environments) can help you if you use `self`. - -> **Note for C++/Java/C# Programmers** -> -> The `self` in Python is equivalent to the `this` pointer in C++ and the `this` reference in Java and C#. - -You must be wondering how Python gives the value for `self` and why you don't need to give a value for it. An example will make this clear. Say you have a class called `MyClass` and an instance of this class called `myobject`. When you call a method of this object as `myobject.method(arg1, arg2)`, this is automatically converted by Python into `MyClass.method(myobject, arg1, arg2)` - this is all the special `self` is about. - -This also means that if you have a method which takes no arguments, then you still have to have one argument - the `self`. - -## Classes {#class} - -The simplest class possible is shown in the following example (save as `oop_simplestclass.py`). - -
{% include "./programs/oop_simplestclass.py" %}
- -Output: - -
{% include "./programs/oop_simplestclass.txt" %}
- -**How It Works** - -We create a new class using the `class` statement and the name of the class. This is followed by an indented block of statements which form the body of the class. In this case, we have an empty block which is indicated using the `pass` statement. - -Next, we create an object/instance of this class using the name of the class followed by a pair of parentheses. (We will learn <> in the next section). For our verification, we confirm the type of the variable by simply printing it. It tells us that we have an instance of the `Person` class in the `__main__` module. - -Notice that the address of the computer memory where your object is stored is also printed. The address will have a different value on your computer since Python can store the object wherever it finds space. - -## Methods - -We have already discussed that classes/objects can have methods just like functions except that we have an extra `self` variable. We will now see an example (save as `oop_method.py`). - -
{% include "./programs/oop_method.py" %}
- -Output: - -
{% include "./programs/oop_method.txt" %}
- -**How It Works** - -Here we see the `self` in action. Notice that the `say_hi` method takes no parameters but still has the `self` in the function definition. - -## The `__init__` method {#init} - -There are many method names which have special significance in Python classes. We will see the significance of the `__init__` method now. - -The `__init__` method is run as soon as an object of a class is instantiated. The method is useful to do any *initialization* you want to do with your object. Notice the double underscores both at the beginning and at the end of the name. - -Example (save as `oop_init.py`): - -
{% include "./programs/oop_init.py" %}
- -Output: - -
{% include "./programs/oop_init.txt" %}
- -**How It Works** - -Here, we define the `__init__` method as taking a parameter `name` (along with the usual `self`). Here, we just create a new field also called `name`. Notice these are two different variables even though they are both called 'name'. There is no problem because the dotted notation `self.name` means that there is something called "name" that is part of the object called "self" and the other `name` is a local variable. Since we explicitly indicate which name we are referring to, there is no confusion. - -When creating new instance `p`, of the class `Person`, we do so by using the class name, followed by the arguments in the parentheses: p = Person('Swaroop'). - -We do not explicitly call the `__init__` method. -This is the special significance of this method. - -Now, we are able to use the `self.name` field in our methods which is demonstrated in the `say_hi` method. - -## Class And Object Variables {#class-obj-vars} - -We have already discussed the functionality part of classes and objects (i.e. methods), now let us learn about the data part. The data part, i.e. fields, are nothing but ordinary variables that are _bound_ to the **namespaces** of the classes and objects. This means that these names are valid within the context of these classes and objects only. That's why they are called _name spaces_. - -There are two types of _fields_ - class variables and object variables which are classified depending on whether the class or the object _owns_ the variables respectively. - -**Class variables** are shared - they can be accessed by all instances of that class. There is only one copy of the class variable and when any one object makes a change to a class variable, that change will be seen by all the other instances. - -**Object variables** are owned by each individual object/instance of the class. In this case, each object has its own copy of the field i.e. they are not shared and are not related in any way to the field by the same name in a different instance. An example will make this easy to understand (save as `oop_objvar.py`): - -
{% include "./programs/oop_objvar.py" %}
- -Output: - -
{% include "./programs/oop_objvar.txt" %}
- -**How It Works** - -This is a long example but helps demonstrate the nature of class and object variables. Here, `population` belongs to the `Robot` class and hence is a class variable. The `name` variable belongs to the object (it is assigned using `self`) and hence is an object variable. - -Thus, we refer to the `population` class variable as `Robot.population` and not as `self.population`. We refer to the object variable `name` using `self.name` notation in the methods of that object. Remember this simple difference between class and object variables. Also note that an object variable with the same name as a class variable will hide the class variable! - -Instead of `Robot.population`, we could have also used `self.__class__.population` because every object refers to it's class via the `self.__class__` attribute. - -The `how_many` is actually a method that belongs to the class and not to the object. This means we can define it as either a `classmethod` or a `staticmethod` depending on whether we need to know which class we are part of. Since we refer to a class variable, let's use `classmethod`. - -We have marked the `how_many` method as a class method using a [decorator](./more.md#decorator). - -Decorators can be imagined to be a shortcut to calling a wrapper function, so applying the `@classmethod` decorator is same as calling: - -```python -how_many = classmethod(how_many) -``` - -Observe that the `__init__` method is used to initialize the `Robot` instance with a name. In this method, we increase the `population` count by 1 since we have one more robot being added. Also observe that the values of `self.name` is specific to each object which indicates the nature of object variables. - -Remember, that you must refer to the variables and methods of the same object using the `self` *only*. This is called an *attribute reference*. - -In this program, we also see the use of *docstrings* for classes as well as methods. We can access the class docstring at runtime using `Robot.__doc__` and the method docstring as `Robot.say_hi.__doc__` - -In the `die` method, we simply decrease the `Robot.population` count by 1. - -All class members are public. One exception: If you use data members with names using the _double underscore prefix_ such as `__privatevar`, Python uses name-mangling to effectively make it a private variable. - -Thus, the convention followed is that any variable that is to be used only within the class or object should begin with an underscore and all other names are public and can be used by other classes/objects. Remember that this is only a convention and is not enforced by Python (except for the double underscore prefix). - -> **Note for C++/Java/C# Programmers** -> -> All class members (including the data members) are _public_ and all the methods are _virtual_ in Python. - -## Inheritance - -One of the major benefits of object oriented programming is **reuse** of code and one of the ways this is achieved is through the **inheritance** mechanism. Inheritance can be best imagined as implementing a **type and subtype** relationship between classes. - -Suppose you want to write a program which has to keep track of the teachers and students in a college. They have some common characteristics such as name, age and address. They also have specific characteristics such as salary, courses and leaves for teachers and, marks and fees for students. - -You can create two independent classes for each type and process them but adding a new common characteristic would mean adding to both of these independent classes. This quickly becomes unwieldy. - -A better way would be to create a common class called `SchoolMember` and then have the teacher and student classes _inherit_ from this class i.e. they will become sub-types of this type (class) and then we can add specific characteristics to these sub-types. - -There are many advantages to this approach. If we add/change any functionality in `SchoolMember`, this is automatically reflected in the subtypes as well. For example, you can add a new ID card field for both teachers and students by simply adding it to the SchoolMember class. However, changes in the subtypes do not affect other subtypes. Another advantage is that if you can refer to a teacher or student object as a `SchoolMember` object which could be useful in some situations such as counting of the number of school members. This is called **polymorphism** where a sub-type can be substituted in any situation where a parent type is expected i.e. the object can be treated as an instance of the parent class. - -Also observe that we reuse the code of the parent class and we do not need to repeat it in the different classes as we would have had to in case we had used independent classes. - -The `SchoolMember` class in this situation is known as the **base class** or the **superclass**. The `Teacher` and `Student` classes are called the **derived classes** or **subclasses**. - -We will now see this example as a program (save as `oop_subclass.py`): - -
{% include "./programs/oop_subclass.py" %}
- -Output: - -
{% include "./programs/oop_subclass.txt" %}
- -**How It Works** - -To use inheritance, we specify the base class names in a tuple following the class name in the class definition. Next, we observe that the `__init__` method of the base class is explicitly called using the `self` variable so that we can initialize the base class part of the object. This is very important to remember - Python does not automatically call the constructor of the base class, you have to explicitly call it yourself. - -We also observe that we can call methods of the base class by prefixing the class name to the method call and then pass in the `self` variable along with any arguments. - -Notice that we can treat instances of `Teacher` or `Student` as just instances of the `SchoolMember` when we use the `tell` method of the `SchoolMember` class. - -Also, observe that the `tell` method of the subtype is called and not the `tell` method of the `SchoolMember` class. One way to understand this is that Python _always_ starts looking for methods in the actual type, which in this case it does. If it could not find the method, it starts looking at the methods belonging to its base classes one by one in the order they are specified in the tuple in the class definition. - -A note on terminology - if more than one class is listed in the inheritance tuple, then it is called **multiple inheritance**. - -The `end` parameter is used in the `print` function in the superclass's `tell()` method to print a line and allow the next print to continue on the same line. This is a trick to make `print` not print a `\n` (newline) symbol at the end of the printing. - -## Summary - -We have now explored the various aspects of classes and objects as well as the various terminologies associated with it. We have also seen the benefits and pitfalls of object-oriented programming. Python is highly object-oriented and understanding these concepts carefully will help you a lot in the long run. - -Next, we will learn how to deal with input/output and how to access files in Python. diff --git a/op_exp.md b/op_exp.md deleted file mode 100644 index 4cfcd7fb..00000000 --- a/op_exp.md +++ /dev/null @@ -1,204 +0,0 @@ -# Operators and Expressions {#op-exp} - -Most statements (logical lines) that you write will contain _expressions_. A simple example of an expression is `2 + 3`. An expression can be broken down into operators and operands. - -_Operators_ are functionality that do something and can be represented by symbols such as `+` or by special keywords. Operators require some data to operate on and such data is called _operands_. In this case, `2` and `3` are the operands. - -## Operators - -We will briefly take a look at the operators and their usage. - -Note that you can evaluate the expressions given in the examples using the interpreter interactively. For example, to test the expression `2 + 3`, use the interactive Python interpreter prompt: - -```python ->>> 2 + 3 -5 ->>> 3 * 5 -15 ->>> -``` - -Here is a quick overview of the available operators: - -- `+` (plus) - - Adds two objects - - `3 + 5` gives `8`. `'a' + 'b'` gives `'ab'`. - -- `-` (minus) - - Gives the subtraction of one number from the other; if the first operand is absent it is assumed to be zero. - - `-5.2` gives a negative number and `50 - 24` gives `26`. - -- `*` (multiply) - - Gives the multiplication of the two numbers or returns the string repeated that many times. - - `2 * 3` gives `6`. `'la' * 3` gives `'lalala'`. - -- `**` (power) - - Returns x to the power of y - - `3 ** 4` gives `81` (i.e. `3 * 3 * 3 * 3`) - -- `/` (divide) - - Divide x by y - - `13 / 3` gives `4.333333333333333` - -- `//` (divide and floor) - - Divide x by y and round the answer _down_ to the nearest whole number - - `13 // 3` gives `4` - - `-13 // 3` gives `-5` - -- `%` (modulo) - - Returns the remainder of the division - - `13 % 3` gives `1`. `-25.5 % 2.25` gives `1.5`. - -- `<<` (left shift) - - Shifts the bits of the number to the left by the number of bits specified. (Each number is represented in memory by bits or binary digits i.e. 0 and 1) - - `2 << 2` gives `8`. `2` is represented by `10` in bits. - - Left shifting by 2 bits gives `1000` which represents the decimal `8`. - -- `>>` (right shift) - - Shifts the bits of the number to the right by the number of bits specified. - - `11 >> 1` gives `5`. - - `11` is represented in bits by `1011` which when right shifted by 1 bit gives `101`which is the decimal `5`. - -- `&` (bit-wise AND) - - Bit-wise AND of the numbers - - `5 & 3` gives `1`. - -- `|` (bit-wise OR) - - Bitwise OR of the numbers - - `5 | 3` gives `7` - -- `^` (bit-wise XOR) - - Bitwise XOR of the numbers - - `5 ^ 3` gives `6` - -- `~` (bit-wise invert) - - The bit-wise inversion of x is -(x+1) - - `~5` gives `-6`. More details at http://stackoverflow.com/a/11810203 - -- `<` (less than) - - Returns whether x is less than y. All comparison operators return `True` or `False`. Note the capitalization of these names. - - `5 < 3` gives `False` and `3 < 5` gives `True`. - - Comparisons can be chained arbitrarily: `3 < 5 < 7` gives `True`. - -- `>` (greater than) - - Returns whether x is greater than y - - `5 > 3` returns `True`. If both operands are numbers, they are first converted to a common type. Otherwise, it always returns `False`. - -- `<=` (less than or equal to) - - Returns whether x is less than or equal to y - - `x = 3; y = 6; x <= y` returns `True` - -- `>=` (greater than or equal to) - - Returns whether x is greater than or equal to y - - `x = 4; y = 3; x >= 3` returns `True` - -- `==` (equal to) - - Compares if the objects are equal - - `x = 2; y = 2; x == y` returns `True` - - `x = 'str'; y = 'stR'; x == y` returns `False` - - `x = 'str'; y = 'str'; x == y` returns `True` - -- `!=` (not equal to) - - Compares if the objects are not equal - - `x = 2; y = 3; x != y` returns `True` - -- `not` (boolean NOT) - - If x is `True`, it returns `False`. If x is `False`, it returns `True`. - - `x = True; not x` returns `False`. - -- `and` (boolean AND) - - `x and y` returns `False` if x is `False`, else it returns evaluation of y - - `x = False; y = True; x and y` returns `False` since x is False. In this case, Python will not evaluate y since it knows that the left hand side of the 'and' expression is `False` which implies that the whole expression will be `False` irrespective of the other values. This is called short-circuit evaluation. - -- `or` (boolean OR) - - If x is `True`, it returns True, else it returns evaluation of y - - `x = True; y = False; x or y` returns `True`. Short-circuit evaluation applies here as well. - -## Shortcut for math operation and assignment - -It is common to run a math operation on a variable and then assign the result of the operation back to the variable, hence there is a shortcut for such expressions: - -```python -a = 2 -a = a * 3 -``` - -can be written as: - -```python -a = 2 -a *= 3 -``` - -Notice that `var = var operation expression` becomes `var operation= expression`. - -## Evaluation Order - -If you had an expression such as `2 + 3 * 4`, is the addition done first or the multiplication? Our high school maths tells us that the multiplication should be done first. This means that the multiplication operator has higher precedence than the addition operator. - -The following table gives the precedence table for Python, from the lowest precedence (least binding) to the highest precedence (most binding). This means that in a given expression, Python will first evaluate the operators and expressions lower in the table before the ones listed higher in the table. - -The following table, taken from the [Python reference manual](http://docs.python.org/3/reference/expressions.html#operator-precedence), is provided for the sake of completeness. It is far better to use parentheses to group operators and operands appropriately in order to explicitly specify the precedence. This makes the program more readable. See [Changing the Order of Evaluation](#changing-order-of-evaluation) below for details. - -- `lambda` : Lambda Expression -- `if - else` : Conditional expression -- `or` : Boolean OR -- `and` : Boolean AND -- `not x` : Boolean NOT -- `in, not in, is, is not, <, <=, >, >=, !=, ==` : Comparisons, including membership tests and identity tests -- `|` : Bitwise OR -- `^` : Bitwise XOR -- `&` : Bitwise AND -- `<<, >>` : Shifts -- `+, -` : Addition and subtraction -- `*, /, //, %` : Multiplication, Division, Floor Division and Remainder -- `+x, -x, ~x` : Positive, Negative, bitwise NOT -- `**` : Exponentiation -- `x[index], x[index:index], x(arguments...), x.attribute` : Subscription, slicing, call, attribute reference -- `(expressions...), [expressions...], {key: value...}, {expressions...}` : Binding or tuple display, list display, dictionary display, set display - -The operators which we have not already come across will be explained in later chapters. - -Operators with the _same precedence_ are listed in the same row in the above table. For example, `+` and `-` have the same precedence. - -## Changing the Order Of Evaluation {#changing-order-of-evaluation} - -To make the expressions more readable, we can use parentheses. For example, `2 + (3 * 4)` is definitely easier to understand than `2 + 3 * 4` which requires knowledge of the operator precedences. As with everything else, the parentheses should be used reasonably (do not overdo it) and should not be redundant, as in `(2 + (3 * 4))`. - -There is an additional advantage to using parentheses - it helps us to change the order of evaluation. For example, if you want addition to be evaluated before multiplication in an expression, then you can write something like `(2 + 3) * 4`. - -## Associativity - -Operators are usually associated from left to right. This means that operators with the same precedence are evaluated in a left to right manner. For example, `2 + 3 + 4` is evaluated as `(2 + 3) + 4`. - -## Expressions - -Example (save as `expression.py`): - -```python -length = 5 -breadth = 2 - -area = length * breadth -print('Area is', area) -print('Perimeter is', 2 * (length + breadth)) -``` - -Output: - -``` -$ python expression.py -Area is 10 -Perimeter is 14 -``` - -**How It Works** - -The length and breadth of the rectangle are stored in variables by the same name. We use these to calculate the area and perimeter of the rectangle with the help of expressions. We store the result of the expression `length * breadth` in the variable +area+ and then print it using the +print+ function. In the second case, we directly use the value of the expression `2 * (length + breadth)` -in the print function. - -Also, notice how Python _pretty-prints_ the output. Even though we have not specified a space between `'Area is'` and the variable `area`, Python puts it for us so that we get a clean nice output and the program is much more readable this way (since we don't need to worry about spacing in the strings we use for output). This is an example of how Python makes life easy for the programmer. - -## Summary - -We have seen how to use operators, operands and expressions - these are the basic building blocks of any program. Next, we will see how to make use of these in our programs using statements. diff --git a/preface.md b/preface.md deleted file mode 100644 index 67083560..00000000 --- a/preface.md +++ /dev/null @@ -1,23 +0,0 @@ -# Preface - -Python is probably one of the few programming languages which is both simple and powerful. This is good for beginners as well as for experts, and more importantly, is fun to program with. This book aims to help you learn this wonderful language and show how to get things done quickly and painlessly - in effect 'The Anti-venom to your programming problems'. - -## Who This Book Is For - -This book serves as a guide or tutorial to the Python programming language. It is mainly targeted at newbies. It is useful for experienced programmers as well. - -The aim is that if all you know about computers is how to save text files, then you can learn Python from this book. If you have previous programming experience, then you can also learn Python from this book. - -If you do have previous programming experience, you will be interested in the differences between Python and your favorite programming language - I have highlighted many such differences. A little warning though, Python is soon going to become your favorite programming language! - -## Official Website - -The official website of the book is {{ book.officialUrl }} where you can read the whole book online, download the latest versions of the book, [buy a printed hard copy]({{ book.buyBookUrl }}) and also send me feedback. - -## Something To Think About - -> There are two ways of constructing a software design: one way is to make it so simple that there are obviously no deficiencies; the other is to make it so complicated that there are no obvious deficiencies. -- C. A. R. Hoare - - - -> Success in life is a matter not so much of talent and opportunity as of concentration and perseverance. -- C. W. Wendte diff --git a/problem_solving.md b/problem_solving.md deleted file mode 100644 index f2a24aa8..00000000 --- a/problem_solving.md +++ /dev/null @@ -1,157 +0,0 @@ -# Problem Solving - -We have explored various parts of the Python language and now we will take a look at how all these parts fit together, by designing and writing a program which _does_ something useful. The idea is to learn how to write a Python script on your own. - -## The Problem - -The problem we want to solve is: - -> I want a program which creates a backup of all my important files. - -Although, this is a simple problem, there is not enough information for us to get started with the solution. A little more *analysis* is required. For example, how do we specify _which_ files are to be backed up? _How_ are they stored? _Where_ are they stored? - -After analyzing the problem properly, we *design* our program. We make a list of things about how our program should work. In this case, I have created the following list on how _I_ want it to work. If you do the design, you may not come up with the same kind of analysis since every person has their own way of doing things, so that is perfectly okay. - -- The files and directories to be backed up are specified in a list. -- The backup must be stored in a main backup directory. -- The files are backed up into a zip file. -- The name of the zip archive is the current date and time. -- We use the standard `zip` command available by default in any standard GNU/Linux or Unix distribution. Note that you can use any archiving command you want as long as it has a command line interface. - -> **For Windows users** -> -> Windows users can [install](http://gnuwin32.sourceforge.net/downlinks/zip.php) the `zip` command from the [GnuWin32 project page](http://gnuwin32.sourceforge.net/packages/zip.htm) and add `C:\Program Files\GnuWin32\bin` to your system `PATH` environment variable, similar to [what we did for recognizing the python command itself](./installation.md#dos-prompt). - -## The Solution - -As the design of our program is now reasonably stable, we can write the code which is an *implementation* of our solution. - -Save as `backup_ver1.py`: - -
{% include "./programs/backup_ver1.py" %}
- -Output: - -
{% include "./programs/backup_ver1.txt" %}
- -Now, we are in the *testing* phase where we test that our program works properly. If it doesn't behave as expected, then we have to *debug* our program i.e. remove the *bugs* (errors) from the program. - -If the above program does not work for you, copy the line printed after the `Zip command is` line in the output, paste it in the shell (on GNU/Linux and Mac OS X) / `cmd` (on Windows), see what the error is and try to fix it. Also check the zip command manual on what could be wrong. If this command succeeds, then the problem might be in the Python program itself, so check if it exactly matches the program written above. - -**How It Works** - -You will notice how we have converted our *design* into *code* in a step-by-step manner. - -We make use of the `os` and `time` modules by first importing them. Then, we specify the files and directories to be backed up in the `source` list. The target directory is where we store all the backup files and this is specified in the `target_dir` variable. The name of the zip archive that we are going to create is the current date and time which we generate using the `time.strftime()` function. It will also have the `.zip` extension and will be stored in the `target_dir` directory. - -Notice the use of the `os.sep` variable - this gives the directory separator according to your operating system i.e. it will be `'/'` in GNU/Linux and Unix, it will be `'\\'` in Windows and `':'` in Mac OS. Using `os.sep` instead of these characters directly will make our program portable and work across all of these systems. - -The `time.strftime()` function takes a specification such as the one we have used in the above program. The `%Y` specification will be replaced by the year with the century. The `%m` specification will be replaced by the month as a decimal number between `01` and `12` and so on. The complete list of such specifications can be found in the [Python Reference Manual](http://docs.python.org/3/library/time.html#time.strftime). - -We create the name of the target zip file using the addition operator which _concatenates_ the strings i.e. it joins the two strings together and returns a new one. Then, we create a string `zip_command` which contains the command that we are going to execute. You can check if this command works by running it in the shell (GNU/Linux terminal or DOS prompt). - -The `zip` command that we are using has some options and parameters passed. The `-r` option specifies that the zip command should work **r**ecursively for directories i.e. it should include all the subdirectories and files. The two options are combined and specified in a shortcut as `-qr`. The options are followed by the name of the zip archive to create followed by the list of files and directories to backup. We convert the `source` list into a string using the `join` method of strings which we have already seen how to use. - -Then, we finally *run* the command using the `os.system` function which runs the command as if it was run from the *system* i.e. in the shell - it returns `0` if the command was successfully, else it returns an error number. - -Depending on the outcome of the command, we print the appropriate message that the backup has failed or succeeded. - -That's it, we have created a script to take a backup of our important files! - -> **Note to Windows Users** -> -> Instead of double backslash escape sequences, you can also use raw strings. For example, use `'C:\\Documents'` or `r'C:\Documents'`. However, do *not* use `'C:\Documents'` since you end up using an unknown escape sequence `\D`. - -Now that we have a working backup script, we can use it whenever we want to take a backup of the files. This is called the *operation* phase or the *deployment* phase of the software. - -The above program works properly, but (usually) first programs do not work exactly as you expect. For example, there might be problems if you have not designed the program properly or if you have made a mistake when typing the code, etc. Appropriately, you will have to go back to the design phase or you will have to debug your program. - -## Second Version - -The first version of our script works. However, we can make some refinements to it so that it can work better on a daily basis. This is called the *maintenance* phase of the software. - -One of the refinements I felt was useful is a better file-naming mechanism - using the _time_ as the name of the file within a directory with the current _date_ as a directory within the main backup directory. The first advantage is that your backups are stored in a hierarchical manner and therefore it is much easier to manage. The second advantage is that the filenames are much shorter. The third advantage is that separate directories will help you check if you have made a backup for each day since the directory would be created only if you have made a backup for that day. - -Save as `backup_ver2.py`: - -
{% include "./programs/backup_ver2.py" %}
- -Output: - -
{% include "./programs/backup_ver2.txt" %}
- -**How It Works** - -Most of the program remains the same. The changes are that we check if there is a directory with the current day as its name inside the main backup directory using the `os.path.exists` function. If it doesn't exist, we create it using the `os.mkdir` function. - -## Third Version - -The second version works fine when I do many backups, but when there are lots of backups, I am finding it hard to differentiate what the backups were for! For example, I might have made some major changes to a program or presentation, then I want to associate what those changes are with the name of the zip archive. This can be easily achieved by attaching a user-supplied comment to the name of the zip archive. - -WARNING: The following program does not work, so do not be alarmed, please follow along because there's a lesson in here. - -Save as `backup_ver3.py`: - -
{% include "./programs/backup_ver3.py" %}
- -Output: - -
{% include "./programs/backup_ver3.txt" %}
- -**How This (does not) Work** - -*This program does not work!* Python says there is a syntax error which means that the script does not satisfy the structure that Python expects to see. When we observe the error given by Python, it also tells us the place where it detected the error as well. So we start *debugging* our program from that line. - -On careful observation, we see that the single logical line has been split into two physical lines but we have not specified that these two physical lines belong together. Basically, Python has found the addition operator (`+`) without any operand in that logical line and hence it doesn't know how to continue. Remember that we can specify that the logical line continues in the next physical line by the use of a backslash at the end of the physical line. So, we make this correction to our program. This correction of the program when we find errors is called *bug fixing*. - -## Fourth Version - -Save as `backup_ver4.py`: - -
{% include "./programs/backup_ver4.py" %}
- -Output: - -
{% include "./programs/backup_ver4.txt" %}
- -**How It Works** - -This program now works! Let us go through the actual enhancements that we had made in version 3. We take in the user's comments using the `input` function and then check if the user actually entered something by finding out the length of the input using the `len` function. If the user has just pressed `enter` without entering anything (maybe it was just a routine backup or no special changes were made), then we proceed as we have done before. - -However, if a comment was supplied, then this is attached to the name of the zip archive just before the `.zip` extension. Notice that we are replacing spaces in the comment with underscores - this is because managing filenames without spaces is much easier. - -## More Refinements - -The fourth version is a satisfactorily working script for most users, but there is always room for improvement. For example, you can include a _verbosity_ level for the program where you can specify a `-v` option to make your program become more talkative or a `-q` to make it _quiet_. - -Another possible enhancement would be to allow extra files and directories to be passed to the script at the command line. We can get these names from the `sys.argv` list and we can add them to our `source` list using the `extend` method provided by the `list` class. - -The most important refinement would be to not use the `os.system` way of creating archives and instead using the [zipfile](http://docs.python.org/3/library/zipfile.html) or [tarfile](http://docs.python.org/3/library/tarfile.html) built-in modules to create these archives. They are part of the standard library and available already for you to use without external dependencies on the zip program to be available on your computer. - -However, I have been using the `os.system` way of creating a backup in the above examples purely for pedagogical purposes, so that the example is simple enough to be understood by everybody but real enough to be useful. - -Can you try writing the fifth version that uses the [zipfile](http://docs.python.org/3/library/zipfile.html) module instead of the `os.system` call? - -## The Software Development Process - -We have now gone through the various *phases* in the process of writing a software. These phases can be summarised as follows: - -1. What (Analysis) -2. How (Design) -3. Do It (Implementation) -4. Test (Testing and Debugging) -5. Use (Operation or Deployment) -6. Maintain (Refinement) - -A recommended way of writing programs is the procedure we have followed in creating the backup script: Do the analysis and design. Start implementing with a simple version. Test and debug it. Use it to ensure that it works as expected. Now, add any features that you want and continue to repeat the Do It-Test-Use cycle as many times as required. - -Remember: - -> Software is grown, not built. -> -- [Bill de hÓra](http://97things.oreilly.com/wiki/index.php/Great_software_is_not_built,_it_is_grown) - -## Summary - -We have seen how to create our own Python programs/scripts and the various stages involved in writing such programs. You may find it useful to create your own program just like we did in this chapter so that you become comfortable with Python as well as problem-solving. - -Next, we will discuss object-oriented programming. diff --git a/programs/backup_ver1.py b/programs/backup_ver1.py index 3841630c..5d1b1168 100644 --- a/programs/backup_ver1.py +++ b/programs/backup_ver1.py @@ -1,37 +1,37 @@ import os import time -# 1. The files and directories to be backed up are -# specified in a list. -# Example on Windows: +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: # source = ['"C:\\My Documents"', 'C:\\Code'] -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 与 Linux 下: source = ['/Users/swa/notes'] -# Notice we had to use double quotes inside the string -# for names with spaces in it. +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 -# 2. The backup must be stored in a -# main backup directory -# Example on Windows: +#2. 备份文件必须存储在一个 +#主备份目录中 +#例如在 Windows 下: # target_dir = 'E:\\Backup' -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 和 Linux 下: target_dir = '/Users/swa/backup' -# Remember to change this to which folder you will be using +# 要记得将这里的目录地址修改至你将使用的路径 -# 3. The files are backed up into a zip file. -# 4. The name of the zip archive is the current date and time +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. zip 压缩文件的文件名由当前日期与时间构成。 target = target_dir + os.sep + \ time.strftime('%Y%m%d%H%M%S') + '.zip' -# Create target directory if it is not present +# 如果目标目录还不存在,则进行创建 if not os.path.exists(target_dir): - os.mkdir(target_dir) # make directory + os.mkdir(target_dir) # 创建目录 -# 5. We use the zip command to put the files in a zip archive +# 5. 我们使用 zip 命令将文件打包成 zip 格式 zip_command = 'zip -r {0} {1}'.format(target, ' '.join(source)) -# Run the backup +# 运行备份 print('Zip command is:') print(zip_command) print('Running:') diff --git a/programs/backup_ver2.py b/programs/backup_ver2.py index caebb985..8b4bd094 100644 --- a/programs/backup_ver2.py +++ b/programs/backup_ver2.py @@ -1,47 +1,46 @@ import os import time -# 1. The files and directories to be backed up are -# specified in a list. -# Example on Windows: +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: # source = ['"C:\\My Documents"', 'C:\\Code'] -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 与 Linux 下: source = ['/Users/swa/notes'] -# Notice we had to use double quotes inside the string -# for names with spaces in it. +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 -# 2. The backup must be stored in a -# main backup directory -# Example on Windows: +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: # target_dir = 'E:\\Backup' -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 和 Linux 下: target_dir = '/Users/swa/backup' -# Remember to change this to which folder you will be using +# 要记得将这里的目录地址修改至你将使用的路径 -# Create target directory if it is not present +# 如果目标目录不存在则创建目录 if not os.path.exists(target_dir): - os.mkdir(target_dir) # make directory + os.mkdir(target_dir) # 创建目录 -# 3. The files are backed up into a zip file. -# 4. The current day is the name of the subdirectory -# in the main directory. +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的子目录名称 today = target_dir + os.sep + time.strftime('%Y%m%d') -# The current time is the name of the zip archive. +# 将当前时间作为 zip 文件的文件名 now = time.strftime('%H%M%S') -# The name of the zip file +# zip 文件名称格式 target = today + os.sep + now + '.zip' -# Create the subdirectory if it isn't already there +# 如果子目录尚不存在则创建一个 if not os.path.exists(today): os.mkdir(today) print('Successfully created directory', today) -# 5. We use the zip command to put the files in a zip archive +# 5. 我们使用 zip 命令将文件打包成 zip 格式 zip_command = 'zip -r {0} {1}'.format(target, ' '.join(source)) -# Run the backup +# 运行备份 print('Zip command is:') print(zip_command) print('Running:') diff --git a/programs/backup_ver3.py b/programs/backup_ver3.py index ac83aca8..81d7b6da 100644 --- a/programs/backup_ver3.py +++ b/programs/backup_ver3.py @@ -1,54 +1,54 @@ import os import time -# 1. The files and directories to be backed up are -# specified in a list. -# Example on Windows: +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: # source = ['"C:\\My Documents"', 'C:\\Code'] -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 与 Linux 下: source = ['/Users/swa/notes'] -# Notice we had to use double quotes inside the string -# for names with spaces in it. +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 -# 2. The backup must be stored in a -# main backup directory -# Example on Windows: +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: # target_dir = 'E:\\Backup' -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 和 Linux 下: target_dir = '/Users/swa/backup' -# Remember to change this to which folder you will be using +# 要记得将这里的目录地址修改至你将使用的路径 -# Create target directory if it is not present +# 如果目标目录还不存在,则进行创建 if not os.path.exists(target_dir): - os.mkdir(target_dir) # make directory + os.mkdir(target_dir) # 创建目录 -# 3. The files are backed up into a zip file. -# 4. The current day is the name of the subdirectory -# in the main directory. +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的 +# 子目录名称 today = target_dir + os.sep + time.strftime('%Y%m%d') -# The current time is the name of the zip archive. +# 将当前时间作为 zip 文件的文件名 now = time.strftime('%H%M%S') -# Take a comment from the user to -# create the name of the zip file +# 添加一条来自用户的注释以创建 +# zip 文件的文件名 comment = input('Enter a comment --> ') -# Check if a comment was entered +# 检查是否有评论键入 if len(comment) == 0: target = today + os.sep + now + '.zip' else: - target = today + os.sep + now + '_' + + target = today + os.sep + now + '_' + comment.replace(' ', '_') + '.zip' -# Create the subdirectory if it isn't already there +# 如果子目录尚不存在则创建一个 if not os.path.exists(today): os.mkdir(today) print('Successfully created directory', today) -# 5. We use the zip command to put the files in a zip archive +# 5. 我们使用 zip 命令将文件打包成 zip 格式 zip_command = "zip -r {0} {1}".format(target, ' '.join(source)) -# Run the backup +# 运行备份 print('Zip command is:') print(zip_command) print('Running:') diff --git a/programs/backup_ver4.py b/programs/backup_ver4.py index c6768333..f3fe811d 100644 --- a/programs/backup_ver4.py +++ b/programs/backup_ver4.py @@ -1,54 +1,54 @@ import os import time -# 1. The files and directories to be backed up are -# specified in a list. -# Example on Windows: +# 1. 需要备份的文件与目录将被 +# 指定在一个列表中。 +# 例如在 Windows 下: # source = ['"C:\\My Documents"', 'C:\\Code'] -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 与 Linux 下: source = ['/Users/swa/notes'] -# Notice we had to use double quotes inside the string -# for names with spaces in it. +# 在这里要注意到我们必须在字符串中使用双引号 +# 用以括起其中包含空格的名称。 -# 2. The backup must be stored in a -# main backup directory -# Example on Windows: +# 2. 备份文件必须存储在一个 +# 主备份目录中 +# 例如在 Windows 下: # target_dir = 'E:\\Backup' -# Example on Mac OS X and Linux: +# 又例如在 Mac OS X 和 Linux 下: target_dir = '/Users/swa/backup' -# Remember to change this to which folder you will be using +# 要记得将这里的目录地址修改至你将使用的路径 -# Create target directory if it is not present +# 如果目标目录还不存在,则进行创建 if not os.path.exists(target_dir): - os.mkdir(target_dir) # make directory + os.mkdir(target_dir) # 创建目录 -# 3. The files are backed up into a zip file. -# 4. The current day is the name of the subdirectory -# in the main directory. +# 3. 备份文件将打包压缩成 zip 文件。 +# 4. 将当前日期作为主备份目录下的 +# 子目录名称 today = target_dir + os.sep + time.strftime('%Y%m%d') -# The current time is the name of the zip archive. +# 将当前时间作为 zip 文件的文件名 now = time.strftime('%H%M%S') -# Take a comment from the user to -# create the name of the zip file +# 添加一条来自用户的注释以创建 +# zip 文件的文件名 comment = input('Enter a comment --> ') -# Check if a comment was entered +# 检查是否有评论键入 if len(comment) == 0: target = today + os.sep + now + '.zip' else: target = today + os.sep + now + '_' + \ comment.replace(' ', '_') + '.zip' -# Create the subdirectory if it isn't already there +# 如果子目录尚不存在则创建一个 if not os.path.exists(today): os.mkdir(today) print('Successfully created directory', today) -# 5. We use the zip command to put the files in a zip archive +# 5. 我们使用 zip 命令将文件打包成 zip 格式 zip_command = 'zip -r {0} {1}'.format(target, ' '.join(source)) -# Run the backup +# 运行备份 print('Zip command is:') print(zip_command) print('Running:') diff --git a/programs/continue.py b/programs/continue.py index fe19c3dd..47a34adf 100644 --- a/programs/continue.py +++ b/programs/continue.py @@ -6,4 +6,4 @@ print('Too small') continue print('Input is of sufficient length') - # Do other kinds of processing here... + # 自此处起继续进行其它任何处理 diff --git a/programs/ds_reference.py b/programs/ds_reference.py index 34d57c6f..7e76b316 100644 --- a/programs/ds_reference.py +++ b/programs/ds_reference.py @@ -1,23 +1,23 @@ print('Simple Assignment') shoplist = ['apple', 'mango', 'carrot', 'banana'] -# mylist is just another name pointing to the same object! +# mylist 只是指向同一对象的另一种名称 mylist = shoplist -# I purchased the first item, so I remove it from the list +# 我购买了第一项项目,所以我将其从列表中删除 del shoplist[0] print('shoplist is', shoplist) print('mylist is', mylist) -# Notice that both shoplist and mylist both print -# the same list without the 'apple' confirming that -# they point to the same object +# 注意到 shoplist 和 mylist 二者都 +# 打印出了其中都没有 apple 的同样的列表,以此我们确认 +# 它们指向的是同一个对象 print('Copy by making a full slice') -# Make a copy by doing a full slice +# 通过生成一份完整的切片制作一份列表的副本 mylist = shoplist[:] -# Remove first item +# 删除第一个项目 del mylist[0] print('shoplist is', shoplist) print('mylist is', mylist) -# Notice that now the two lists are different +# 注意到现在两份列表已出现不同 diff --git a/programs/ds_seq.py b/programs/ds_seq.py index 52d2d5cf..fec0c24e 100644 --- a/programs/ds_seq.py +++ b/programs/ds_seq.py @@ -2,6 +2,7 @@ name = 'swaroop' # Indexing or 'Subscription' operation # +# 索引或“下标(Subscription)”操作符 # print('Item 0 is', shoplist[0]) print('Item 1 is', shoplist[1]) print('Item 2 is', shoplist[2]) @@ -16,7 +17,7 @@ print('Item 1 to -1 is', shoplist[1:-1]) print('Item start to end is', shoplist[:]) -# Slicing on a string # +# 从某一字符串中切片 # print('characters 1 to 3 is', name[1:3]) print('characters 2 to end is', name[2:]) print('characters 1 to -1 is', name[1:-1]) diff --git a/programs/ds_str_methods.py b/programs/ds_str_methods.py index b8d03d5f..b068a123 100644 --- a/programs/ds_str_methods.py +++ b/programs/ds_str_methods.py @@ -1,4 +1,4 @@ -# This is a string object +# 这是一个字符串对象 name = 'Swaroop' if name.startswith('Swa'): diff --git a/programs/ds_using_dict.py b/programs/ds_using_dict.py index 8cae7e28..5477633e 100644 --- a/programs/ds_using_dict.py +++ b/programs/ds_using_dict.py @@ -1,4 +1,4 @@ -# 'ab' is short for 'a'ddress'b'ook +# “ab”是地址(Address)簿(Book)的缩写 ab = { 'Swaroop': 'swaroop@swaroopch.com', @@ -9,7 +9,7 @@ print("Swaroop's address is", ab['Swaroop']) -# Deleting a key-value pair +# 删除一对键值—值配对 del ab['Spammer'] print('\nThere are {} contacts in the address-book\n'.format(len(ab))) @@ -17,7 +17,7 @@ for name, address in ab.items(): print('Contact {} at {}'.format(name, address)) -# Adding a key-value pair +# 添加一对键值—值配对 ab['Guido'] = 'guido@python.org' if 'Guido' in ab: diff --git a/programs/ds_using_tuple.py b/programs/ds_using_tuple.py index 2c13a528..09c97745 100644 --- a/programs/ds_using_tuple.py +++ b/programs/ds_using_tuple.py @@ -1,7 +1,7 @@ -# I would recommend always using parentheses -# to indicate start and end of tuple -# even though parentheses are optional. -# Explicit is better than implicit. +# 我会推荐你总是使用括号 +# 来指明元组的开始与结束 +# 尽管括号是一个可选选项。 +# 明了胜过晦涩,显式优于隐式。 zoo = ('python', 'elephant', 'penguin') print('Number of animals in the zoo is', len(zoo)) diff --git a/programs/exceptions_finally.py b/programs/exceptions_finally.py index b4d3ffb2..3ca846b7 100644 --- a/programs/exceptions_finally.py +++ b/programs/exceptions_finally.py @@ -4,7 +4,7 @@ f = None try: f = open("poem.txt") - # Our usual file-reading idiom + # 我们常用的文件阅读风格 while True: line = f.readline() if len(line) == 0: @@ -12,7 +12,7 @@ print(line, end='') sys.stdout.flush() print("Press ctrl+c now") - # To make sure it runs for a while + # 为了确保它能运行一段时间 time.sleep(2) except IOError: print("Could not find file poem.txt") diff --git a/programs/exceptions_raise.py b/programs/exceptions_raise.py index 407ac9da..e8136135 100644 --- a/programs/exceptions_raise.py +++ b/programs/exceptions_raise.py @@ -1,5 +1,7 @@ +# encoding=UTF-8 + class ShortInputException(Exception): - '''A user-defined exception class.''' + '''一个由用户定义的异常类''' def __init__(self, length, atleast): Exception.__init__(self) self.length = length @@ -9,7 +11,7 @@ def __init__(self, length, atleast): text = input('Enter something --> ') if len(text) < 3: raise ShortInputException(len(text), 3) - # Other work can continue as usual here + # 其他工作能在此处继续正常运行 except EOFError: print('Why did you do an EOF on me?') except ShortInputException as ex: diff --git a/programs/function1.py b/programs/function1.py index 3351cd08..249d9826 100644 --- a/programs/function1.py +++ b/programs/function1.py @@ -1,7 +1,7 @@ def say_hello(): - # block belonging to the function + # 该块属于这一函数 print('hello world') -# End of function +# 函数结束 -say_hello() # call the function -say_hello() # call the function again +say_hello() # 调用函数 +say_hello() # 再次调用函数 diff --git a/programs/function_docstring.py b/programs/function_docstring.py index 1c9035dc..d4204f41 100644 --- a/programs/function_docstring.py +++ b/programs/function_docstring.py @@ -1,8 +1,8 @@ def print_max(x, y): - '''Prints the maximum of two numbers. + '''打印两个数值中的最大数。 - The two values must be integers.''' - # convert to integers, if possible + 这两个数都应该是整数''' + # 如果可能,将其转换至整数类型 x = int(x) y = int(y) diff --git a/programs/function_docstring.txt b/programs/function_docstring.txt index 1995f796..b4a25ab2 100644 --- a/programs/function_docstring.txt +++ b/programs/function_docstring.txt @@ -1,5 +1,5 @@ $ python function_docstring.py 5 is maximum -Prints the maximum of two numbers. +打印两个数值中的最大数。 - The two values must be integers. + 这两个数都应该是整数 diff --git a/programs/function_param.py b/programs/function_param.py index ae9778da..af99dfc5 100644 --- a/programs/function_param.py +++ b/programs/function_param.py @@ -6,11 +6,11 @@ def print_max(a, b): else: print(b, 'is maximum') -# directly pass literal values +# 直接传递字面值 print_max(3, 4) x = 5 y = 7 -# pass variables as arguments +# 以参数的形式传递变量 print_max(x, y) diff --git a/programs/function_varargs.py b/programs/function_varargs.py index 22db80d2..ce6fceef 100644 --- a/programs/function_varargs.py +++ b/programs/function_varargs.py @@ -1,11 +1,11 @@ def total(a=5, *numbers, **phonebook): print('a', a) - - #iterate through all the items in tuple + + #遍历元组中的所有项目 for single_item in numbers: print('single_item', single_item) - - #iterate through all the items in dictionary + + #遍历字典中的所有项目 for first_part, second_part in phonebook.items(): print(first_part,second_part) diff --git a/programs/if.py b/programs/if.py index d4cd3e23..3faab483 100644 --- a/programs/if.py +++ b/programs/if.py @@ -2,18 +2,18 @@ guess = int(input('Enter an integer : ')) if guess == number: - # New block starts here + # 新块从这里开始 print('Congratulations, you guessed it.') print('(but you do not win any prizes!)') - # New block ends here + # 新块在这里结束 elif guess < number: - # Another block + # 另一代码块 print('No, it is a little higher than that') - # You can do whatever you want in a block ... + # 你可以在此做任何你希望在该代码块内进行的事情 else: print('No, it is a little lower than that') - # you must have guessed > number to reach here + # 你必须通过猜测一个大于(>)设置数的数字来到达这里。 print('Done') -# This last statement is always executed, -# after the if statement is executed. +# 这最后一句语句将在 +# if 语句执行完毕后执行。 diff --git a/programs/io_pickle.py b/programs/io_pickle.py index 1fd345cf..a696794a 100644 --- a/programs/io_pickle.py +++ b/programs/io_pickle.py @@ -1,21 +1,21 @@ import pickle -# The name of the file where we will store the object +# 我们存储相关对象的文件的名称 shoplistfile = 'shoplist.data' -# The list of things to buy +# 需要购买的物品清单 shoplist = ['apple', 'mango', 'carrot'] -# Write to the file +# 准备写入文件 f = open(shoplistfile, 'wb') -# Dump the object to a file +# 转储对象至文件 pickle.dump(shoplist, f) f.close() -# Destroy the shoplist variable +# 清除 shoplist 变量 del shoplist -# Read back from the storage +# 重新打开存储文件 f = open(shoplistfile, 'rb') -# Load the object from the file +# 从文件中载入对象 storedlist = pickle.load(f) print(storedlist) diff --git a/programs/io_using_file.py b/programs/io_using_file.py index 28a0f857..68bd4d05 100644 --- a/programs/io_using_file.py +++ b/programs/io_using_file.py @@ -5,24 +5,24 @@ use Python! ''' -# Open for 'w'riting +# 打开文件以编辑('w'riting) f = open('poem.txt', 'w') -# Write text to file +# 向文件中编写文本 f.write(poem) -# Close the file +# 关闭文件 f.close() -# If no mode is specified, -# 'r'ead mode is assumed by default +# 如果没有特别指定, +# 将假定启用默认的阅读('r'ead)模式 f = open('poem.txt') while True: line = f.readline() - # Zero length indicates EOF + # 零长度指示 EOF if len(line) == 0: break - # The `line` already has a newline - # at the end of each line - # since it is reading from a file. + # 每行(`line`)的末尾 + # 都已经有了换行符 + #因为它是从一个文件中进行读取的 print(line, end='') -# close the file +# 关闭文件 f.close() diff --git a/programs/more_decorator.py b/programs/more_decorator.py index 52b7f3ed..73be9aa9 100644 --- a/programs/more_decorator.py +++ b/programs/more_decorator.py @@ -33,8 +33,8 @@ def save_to_database(arg): print("This will be automatically retried if exception is thrown.") global counter counter += 1 - # This will throw an exception in the first call - # And will work fine in the second call (i.e. a retry) + # 这将在第一次调用时抛出异常 + # 在第二次运行时将正常工作(也就是重试) if counter < 2: raise ValueError(arg) diff --git a/programs/oop_init.py b/programs/oop_init.py index 2eb30e11..e41391be 100644 --- a/programs/oop_init.py +++ b/programs/oop_init.py @@ -7,5 +7,5 @@ def say_hi(self): p = Person('Swaroop') p.say_hi() -# The previous 2 lines can also be written as -# Person('Swaroop').say_hi() +# 前面两行同时也能写作 +# Person('Swaroop').say_hi() \ No newline at end of file diff --git a/programs/oop_method.py b/programs/oop_method.py index e7d5e201..faad700e 100644 --- a/programs/oop_method.py +++ b/programs/oop_method.py @@ -4,5 +4,5 @@ def say_hi(self): p = Person() p.say_hi() -# The previous 2 lines can also be written as -# Person().say_hi() +# 前面两行同样可以写作 +# Person().say_hi() \ No newline at end of file diff --git a/programs/oop_objvar.py b/programs/oop_objvar.py index 2e6bacbf..bccc837b 100644 --- a/programs/oop_objvar.py +++ b/programs/oop_objvar.py @@ -1,20 +1,22 @@ +# coding=UTF-8 + class Robot: - """Represents a robot, with a name.""" + """表示有一个带有名字的机器人。""" - # A class variable, counting the number of robots + # 一个类变量,用来计数机器人的数量 population = 0 def __init__(self, name): - """Initializes the data.""" + """初始化数据""" self.name = name print("(Initializing {})".format(self.name)) - # When this person is created, the robot - # adds to the population + # 当有人被创建时,机器人 + # 将会增加人口数量 Robot.population += 1 def die(self): - """I am dying.""" + """我挂了。""" print("{} is being destroyed!".format(self.name)) Robot.population -= 1 @@ -26,14 +28,14 @@ def die(self): Robot.population)) def say_hi(self): - """Greeting by the robot. + """来自机器人的诚挚问候 - Yeah, they can do that.""" + 没问题,你做得到。""" print("Greetings, my masters call me {}.".format(self.name)) @classmethod def how_many(cls): - """Prints the current population.""" + """打印出当前的人口数量""" print("We have {:d} robots.".format(cls.population)) diff --git a/programs/oop_simplestclass.py b/programs/oop_simplestclass.py index a49ba831..c60af817 100644 --- a/programs/oop_simplestclass.py +++ b/programs/oop_simplestclass.py @@ -1,5 +1,5 @@ class Person: - pass # An empty block + pass # 一个空的代码块 p = Person() print(p) diff --git a/programs/oop_subclass.py b/programs/oop_subclass.py index 780339b0..11e189f4 100644 --- a/programs/oop_subclass.py +++ b/programs/oop_subclass.py @@ -1,17 +1,19 @@ +# coding=UTF-8 + class SchoolMember: - '''Represents any school member.''' + '''代表任何学校里的成员。''' def __init__(self, name, age): self.name = name self.age = age print('(Initialized SchoolMember: {})'.format(self.name)) def tell(self): - '''Tell my details.''' + '''告诉我有关我的细节。''' print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ") class Teacher(SchoolMember): - '''Represents a teacher.''' + '''代表一位老师。''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary @@ -23,7 +25,7 @@ def tell(self): class Student(SchoolMember): - '''Represents a student.''' + '''代表一位学生。''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks @@ -36,10 +38,10 @@ def tell(self): t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 25, 75) -# prints a blank line +# 打印一行空白行 print() members = [t, s] for member in members: - # Works for both Teachers and Students + # 对全体师生工作 member.tell() diff --git a/programs/while.py b/programs/while.py index 682c15ff..798a92d4 100644 --- a/programs/while.py +++ b/programs/while.py @@ -6,7 +6,7 @@ if guess == number: print('Congratulations, you guessed it.') - # this causes the while loop to stop + # 这将导致 while 循环中止 running = False elif guess < number: print('No, it is a little higher than that.') @@ -14,6 +14,6 @@ print('No, it is a little lower than that.') else: print('The while loop is over.') - # Do anything else you want to do here + # 在这里你可以做你想做的任何事 print('Done') diff --git a/revision_history.md b/revision_history.md deleted file mode 100644 index bb0e840d..00000000 --- a/revision_history.md +++ /dev/null @@ -1,105 +0,0 @@ -# Appendix: History Lesson {#history-lesson} - -I first started with Python when I needed to write an installer for software I had written called 'Diamond' so that I could make the installation easy. I had to choose between Python and Perl bindings for the Qt library. I did some research on the web and I came across [an article by Eric S. Raymond](http://www.python.org/about/success/esr/), a famous and respected hacker, where he talked about how Python had become his favorite programming language. I also found out that the PyQt bindings were more mature compared to Perl-Qt. So, I decided that Python was the language for me. - -Then, I started searching for a good book on Python. I couldn't find any! I did find some O'Reilly books but they were either too expensive or were more like a reference manual than a guide. So, I settled for the documentation that came with Python. However, it was too brief and small. It did give a good idea about Python but was not complete. I managed with it since I had previous programming experience, but it was unsuitable for newbies. - -About six months after my first brush with Python, I installed the (then) latest Red Hat 9.0 Linux and I was playing around with KWord. I got excited about it and suddenly got the idea of writing some stuff on Python. I started writing a few pages but it quickly became 30 pages long. Then, I became serious about making it more useful in a book form. After a _lot_ of rewrites, it has reached a stage where it has become a useful guide to learning the Python language. I consider this book to be my contribution and tribute to the open source community. - -This book started out as my personal notes on Python and I still consider it in the same way, although I've taken a lot of effort to make it more palatable to others :) - -In the true spirit of open source, I have received lots of constructive suggestions, criticisms and [feedback](./README.md#who-reads-bop) from enthusiastic readers which has helped me improve this book a lot. - -## Status Of The Book - -The book needs the help of its readers such as yourselves to point out any parts of the book which are not good, not comprehensible or are simply wrong. Please [write to the main author]({{ book.contactUrl }}) or the respective [translators](./translations.md#translations) with your comments and suggestions. - -# Appendix: Revision History {#revision-history} - -- 4.0 - - 19 Jan 2016 - - Switched back to Python 3 - - Switched back to Markdown, using [GitBook](https://www.gitbook.com) and [Spacemacs](http://spacemacs.org) - -- 3.0 - - 31 Mar 2014 - - Rewritten for Python 2 using [AsciiDoc](http://asciidoctor.org/docs/what-is-asciidoc/) and [adoc-mode](https://github.com/sensorflo/adoc-mode/wiki). - -- 2.1 - - 03 Aug 2013 - - Rewritten using Markdown and [Jason Blevins' Markdown Mode](http://jblevins.org/projects/markdown-mode/) - -- 2.0 - - 20 Oct 2012 - - Rewritten in [Pandoc format](http://johnmacfarlane.net/pandoc/README.html), thanks to my wife who did most of the conversion from the Mediawiki format - - Simplifying text, removing non-essential sections such as `nonlocal` and metaclasses - -- 1.90 - - 04 Sep 2008 and still in progress - - Revival after a gap of 3.5 years! - - Rewriting for Python 3.0 - - Rewrite using http://www.mediawiki.org[MediaWiki] (again) - -- 1.20 - - 13 Jan 2005 - - Complete rewrite using [Quanta+](https://en.wikipedia.org/wiki/Quanta_Plus) on [Fedora](http://fedoraproject.org/) Core 3 with lot of corrections and updates. Many new examples. Rewrote my DocBook setup from scratch. - -- 1.15 - - 28 Mar 2004 - - Minor revisions - -- 1.12 - - 16 Mar 2004 - - Additions and corrections - -- 1.10 - - 09 Mar 2004 - - More typo corrections, thanks to many enthusiastic and helpful readers. - -- 1.00 - - 08 Mar 2004 - - After tremendous feedback and suggestions from readers, I have made significant revisions to the content along with typo corrections. - -- 0.99 - - 22 Feb 2004 - - Added a new chapter on modules. Added details about variable number of arguments in functions. - -- 0.98 - - 16 Feb 2004 - - Wrote a Python script and CSS stylesheet to improve XHTML output, including a crude-yet-functional lexical analyzer for automatic VIM-like syntax highlighting of the program listings. - -- 0.97 - - 13 Feb 2004 - - Another completely rewritten draft, in DocBook XML (again). Book has improved a lot - it is more coherent and readable. - -- 0.93 - - 25 Jan 2004 - - Added IDLE talk and more Windows-specific stuff - -- 0.92 - - 05 Jan 2004 - - Changes to few examples. - -- 0.91 - - 30 Dec 2003 - - Corrected typos. Improvised many topics. - -- 0.90 - - 18 Dec 2003 - - Added 2 more chapters. [OpenOffice](https://en.wikipedia.org/wiki/OpenOffice) format with revisions. - -- 0.60 - - 21 Nov 2003 - - Fully rewritten and expanded. - -- 0.20 - - 20 Nov 2003 - - Corrected some typos and errors. - -- 0.15 - - 20 Nov 2003 - - Converted to [DocBook XML](https://en.wikipedia.org/wiki/DocBook) with XEmacs. - -- 0.10 - - 14 Nov 2003 - - Initial draft using [KWord](https://en.wikipedia.org/wiki/Kword). diff --git a/stdlib.md b/stdlib.md deleted file mode 100644 index 4290d07b..00000000 --- a/stdlib.md +++ /dev/null @@ -1,67 +0,0 @@ -# Standard Library {#stdlib} - -The Python Standard Library contains a huge number of useful modules and is part of every standard Python installation. It is important to become familiar with the Python Standard Library since many problems can be solved quickly if you are familiar with the range of things that these libraries can do. - -We will explore some of the commonly used modules in this library. You can find complete details for all of the modules in the Python Standard Library in the ['Library Reference' section](http://docs.python.org/3/library/) of the documentation that comes with your Python installation. - -Let us explore a few useful modules. - -> CAUTION: If you find the topics in this chapter too advanced, you may skip this chapter. However, I highly recommend coming back to this chapter when you are more comfortable with programming using Python. - -## `sys` module {#sys} - -The `sys` module contains system-specific functionality. We have already seen that the `sys.argv` list contains the command-line arguments. - -Suppose we want to check the version of the Python software being used, the `sys` module gives us that information. - - -```python ->>> import sys ->>> sys.version_info -sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0) ->>> sys.version_info.major == 3 -True -``` - -**How It Works** - -The `sys` module has a `version_info` tuple that gives us the version information. The first entry is the major version. We can pull out this information to use it. - -## logging module {#logging} - -What if you wanted to have some debugging messages or important messages to be stored somewhere so that you can check whether your program has been running as you would expect it? How do you "store somewhere" these messages? This can be achieved using the `logging` module. - -Save as `stdlib_logging.py`: - -
{% include "./programs/stdlib_logging.py" %}
- -Output: - -
{% include "./programs/stdlib_logging.txt" %}
- -If you do not have the `cat` command, then you can just open the `test.log` file in a text editor. - -**How It Works** - -We use three modules from the standard library - the `os` module for interacting with the operating system, the `platform` module for information about the platform i.e. the operating system and the `logging` module to *log* information. - -First, we check which operating system we are using by checking the string returned by `platform.platform()` (for more information, see `import platform; help(platform)`). If it is Windows, we figure out the home drive, the home folder and the filename where we want to store the information. Putting these three parts together, we get the full location of the file. For other platforms, we need to know just the home folder of the user and we get the full location of the file. - -We use the `os.path.join()` function to put these three parts of the location together. The reason to use a special function rather than just adding the strings together is because this function will ensure the full location matches the format expected by the operating system. - -We configure the `logging` module to write all the messages in a particular format to the file we have specified. - -Finally, we can put messages that are either meant for debugging, information, warning or even critical messages. Once the program has run, we can check this file and we will know what happened in the program, even though no information was displayed to the user running the program. - -## Module of the Week Series {#motw} - -There is much more to be explored in the standard library such as [debugging](http://docs.python.org/3/library/pdb.html), -[handling command line options](http://docs.python.org/3/library/argparse.html), [regular expressions](http://docs.python.org/3/library/re.html) and so on. - -The best way to further explore the standard library is to read Doug Hellmann's excellent [Python Module of the Week](http://pymotw.com/2/contents.html) series (also available as a [book](http://amzn.com/0321767349)) and reading the [Python documentation](http://docs.python.org/3/). - -## Summary - -We have explored some of the functionality of many modules in the Python Standard Library. It is highly recommended to browse through the [Python Standard Library documentation](http://docs.python.org/3/library/) to get an idea of all the modules that are available. - -Next, we will cover various aspects of Python that will make our tour of Python more _complete_. diff --git a/styles/pdf.css b/styles/pdf.css new file mode 100644 index 00000000..4b9a78db --- /dev/null +++ b/styles/pdf.css @@ -0,0 +1 @@ +/* CSS for pdf */ diff --git a/styles/website.css b/styles/website.css new file mode 100644 index 00000000..6f5520e4 --- /dev/null +++ b/styles/website.css @@ -0,0 +1,5 @@ +/* CSS for website */ + +.book .book-summary, .book .book-body { + font-family: "Tsentsiu HG", "Source Han Sans", "Microsoft YaHei UI", "Microsoft Yahei", "PingFang SC", "Lantinghei SC", "Hiragino Sans GB", "WenQuanYi Micro Hei", "WenQuanYi Zen Hei", "Noto Sans CJK SC", "Microsoft JhengHei UI", "Microsoft JhengHei", "PingFang TC", "Lantinghei TC", "Noto Sans CJK TC", "Helvetica Neue", Helvetica, Arial, sans-serif; +} diff --git a/translation_howto.md b/translation_howto.md deleted file mode 100644 index e29615a5..00000000 --- a/translation_howto.md +++ /dev/null @@ -1,8 +0,0 @@ -# Translation How-to {#translation-howto} - -1. The full source of the book is available from {{ book.sourceUrl }}. -2. Please [fork the repository](https://help.github.com/articles/fork-a-repo). -3. Then, fetch the repository to your computer. You need to know how to use [Git](http://www.git-scm.com) to do that. -4. Read the [GitBook documentation](https://help.gitbook.com), esp. the [Markdown section](https://help.gitbook.com/format/markdown.html). -5. Start editing the `.md` files to translate to your local language. -6. [Sign up on GitBook.com](https://www.gitbook.com), create a book and you can see a beautifully rendered website, with links to download PDF, EPUB, etc. diff --git a/translations.md b/translations.md deleted file mode 100644 index d75b6a4c..00000000 --- a/translations.md +++ /dev/null @@ -1,201 +0,0 @@ -# Translations - -There are many translations of the book available in different human languages, thanks to many tireless volunteers! - -If you want to help with these translations, please see the list of volunteers and languages below and decide if you want to start a new translation or help in existing translation projects. - -If you plan to start a new translation, please read the [Translation how-to](./translation_howto.md#translation-howto). - -## Arabic - -Below is the link for the Arabic version. Thanks to Ashraf Ali Khalaf for translating the book, you can read the whole book online at or you can download it from [sourceforge.net](http://downloads.sourceforge.net/omlx/byteofpython_arabic.pdf?use_mirror=osdn) for more info see . - -## Azerbaijani - -Jahangir Shabiyev (c.shabiev@gmail.com) has volunteered to translate the book to Azerbaijani. The translation is in progress at https://www.gitbook.com/book/jahangir-sh/piton-sancmasi - - -## Brazilian Portuguese - -There are two translations in various levels of completion and accessibility. The older translation is now missing/lost, and newer translation is incomplete. - -Samuel Dias Neto (samuel.arataca@gmail.com) made the first Brazilian Portuguese translation (older translation) of this book when Python was in 2.3.5 version. This is no longer publicly accessible. - -[Rodrigo Amaral](http://rodrigoamaral.net) (rodrigoamaral@gmail.com) has volunteered to translate the book to Brazilian Portuguese, (newer translation) which still remains to be completed. - -## Catalan - -Moises Gomez (moisesgomezgiron@gmail.com) has volunteered to translate the book to Catalan. The translation is in progress. - -> Moisès Gómez - I am a developer and also a teacher of programming (normally for people without any previous experience). -> -> Some time ago I needed to learn how to program in Python, and Swaroop's work was really helpful. Clear, concise, and complete enough. Just what I needed. -> -> After this experience, I thought some other people in my country could take benefit from it too. But English language can be a barrier. -> -> So, why not try to translate it? And I did for a previous version of BoP. -> -> I my country there are two official languages. I selected the Catalan language assuming that others will translate it to the more widespread Spanish. - -## Chinese - -Translations are available at and . - -Juan Shen (orion_val@163.com) has volunteered to translate the book to Chinese. - -> I am a postgraduate at Wireless Telecommunication Graduate School, Beijing University of Technology, China PR. My current research interest is on the synchronization, channel estimation and multi-user detection of multicarrier CDMA system. Python is my major programming language for daily simulation and research job, with the help of Python Numeric, actually. I learned Python just half a year before, but as you can see, it's really easy-understanding, easy-to-use and productive. Just as what is ensured in Swaroop's book, 'It's my favorite programming language now'. -> -> 'A Byte of Python' is my tutorial to learn Python. It's clear and effective to lead you into a world of Python in the shortest time. It's not too long, but efficiently covers almost all important things in Python. I think 'A Byte of Python' should be strongly recommendable for newbies as their first Python tutorial. Just dedicate my translation to the potential millions of Python users in China. - -## Chinese Traditional - -Fred Lin (gasolin@gmail.com) has volunteered to translate the book to Chinese Traditional. - -It is available at . - -An exciting feature of this translation is that it also contains the _executable chinese python sources_ side by side with the original python sources. - -> Fred Lin - I'm working as a network firmware engineer at Delta Network, and I'm also a contributor of TurboGears web framework. -> -> As a python evangelist (:-p), I need some material to promote python language. I found 'A Byte of Python' hit the sweet point for both newbies and experienced programmers. 'A Byte of Python' elaborates the python essentials with affordable size. -> -> The translation are originally based on simplified chinese version, and soon a lot of rewrite were made to fit the current wiki version and the quality of reading. -> -> The recent chinese traditional version also featured with executable chinese python sources, which are achieved by my new 'zhpy' (python in chinese) project (launch from Aug 07). -> -> zhpy(pronounce (Z.H.?, or zippy) build a layer upon python to translate or interact with python in chinese(Traditional or Simplified). This project is mainly aimed for education. - -## French - -Gregory (coulix@ozforces.com.au) has volunteered to translate the book to French. - -Gérard Labadie (gerard.labadie@gmail.com) has completed to translate the book to French. - -## German - -Lutz Horn (lutz.horn@gmx.de), Bernd Hengelein (bernd.hengelein@gmail.com) and Christoph Zwerschke (cito@online.de) have volunteered to translate the book to German. - -Their translation is located at - -Lutz Horn says: - -> I'm 32 years old and have a degree of Mathematics from University of Heidelberg, Germany. Currently I'm working as a software engineer on a publicly funded project to build a web portal for all things related to computer science in Germany.The main language I use as a professional is Java, but I try to do as much as possible with Python behind the scenes. Especially text analysis and conversion is very easy with Python. I'm not very familiar with GUI toolkits, since most of my programming is about web applications, where the user interface is build using Java frameworks like Struts. Currently I try to make more use of the functional programming features of Python and of generators. After taking a short look into Ruby, I was very impressed with the use of blocks in this language. Generally I like the dynamic nature of languages like Python and Ruby since it allows me to do things not possible in more static languages like Java.I've searched for some kind of introduction to programming, suitable to teach a complete non-programmer. I've found the book 'How to Think Like a Computer Scientist: Learning with Python', and 'Dive into Python'. The first is good for beginners but to long to translate. The second is not suitable for beginners. I think 'A Byte of Python' falls nicely between these, since it is not too long, written to the point, and at the same time verbose enough to teach a newbie. Besides this, I like the simple DocBook structure, which makes translating the text a generation the output in various formats a charm. - -Bernd Hengelein says: - -> Lutz and me are going to do the german translation together. We just started with the intro and preface but we will keep you informed about the progress we make. Ok, now some personal things about me. I am 34 years old and playing with computers since the 1980's, when the "Commodore C64" ruled the nurseries. After studying computer science I started working as a software engineer. Currently I am working in the field of medical imaging for a major german company. Although C++ is the main language I (have to) use for my daily work, I am constantly looking for new things to learn.Last year I fell in love with Python, which is a wonderful language, both for its possibilities and its beauty. I read somewhere in the net about a guy who said that he likes python, because the code looks so beautiful. In my opinion he's absolutly right. At the time I decided to learn python, I noticed that there is very little good documentation in german available. When I came across your book the spontaneous idea of a german translation crossed my mind. Luckily, Lutz had the same idea and we can now divide the work.I am looking forward to a good cooperation! - -## Greek - -The Greek Ubuntu Community [translated the book in Greek](http://wiki.ubuntu-gr.org/byte-of-python-el), for use in our on-line asynchronous Python lessons that take place in our forums. Contact [@savvasradevic](https://twitter.com/savvasradevic) for more information. - -## Indonesian - -Daniel (daniel.mirror@gmail.com) is translating the book to Indonesian at . - -Wisnu Priyambodo (cibermen@gmail.com) also has volunteered to translate the book to Indonesian. - -Also, Bagus Aji Santoso (baguzzzaji@gmail.com) has volunteered. - -## Italian (first) - -Enrico Morelli (mr.mlucci@gmail.com) and Massimo Lucci (morelli@cerm.unifi.it) have volunteered to translate the book to Italian. - -The Italian translation is present at . - -> _Massimo Lucci and Enrico Morelli_ - we are working at the University of Florence (Italy) - Chemistry Department. I (Massimo) as service engineer and system administrator for Nuclear Magnetic Resonance Spectrometers; Enrico as service engineer and system administrator for our CED and parallel / clustered systems. We are programming on python since about seven years, we had experience working with Linux platforms since ten years. In Italy we are responsible and administrator for www.gentoo.it web site for Gentoo/Linux distrubution and www.nmr.it (now under construction) for Nuclear Magnetic Resonance applications and Congress Organization and Managements.That's all! We are impressed by the smart language used on your Book and we think this is essential for approaching the Python to new users (we are thinking about hundred of students and researcher working on our labs). - -## Italian (second) - -An Italian translation has been created by -[Calvina Bice](http://besthcgdropswebsite.com/translate) & colleagues at . - -## Japanese - -Shunro Dozono (dozono@gmail.com) is translating the book to Japanese. - -## Korean - -Jeongbin Park (pjb7687@gmail.com) has translated the book to Korean - - -> I am Jeongbin Park, currently working as a Biophysics & Bioinformatics researcher in Korea. -> -> A year ago, I was looking for a good tutorial/guide for Python to introduce it to my colleagues, because using Python in such research fields is becoming inevitable due to the user base is growing more and more. -> -> But at that time only few Python books are available in Korean, so I decided to translate your ebook because it looks like one of the best guides that I have ever read! -> -> Currently, the book is almost completely translated in Korean, except some of the text in introduction chapter and the appendixes. -> -> Thank you again for writing such a good guide! - -## Mongolian - -Ariunsanaa Tunjin (luftballons2010@gmail.com) has volunteered to translate the book to Mongolian. - -_Update on Nov 22, 2009_ : Ariunsanaa is on the verge of completing the translation. - -## Norwegian (bokmål) - -Eirik Vågeskar is a high school student at [Sandvika videregående skole](http://no.wikipedia.org/wiki/Sandvika_videreg%C3%A5ende_skole) in Norway, a [blogger](http://forbedre.blogspot.com/) and currently translating the book to Norwegian (bokmål). - -> _Eirik Vågeskar_: I have always wanted to program, but because I speak a small language, the learning process was much harder. Most tutorials and books are written in very technical English, so most high school graduates will not even have the vocabulary to understand what the tutorial is about. When I discovered this book, all my problems were solved. "A Byte of Python" used simple non-technical language to explain a programming language that is just as simple, and these two things make learning Python fun. After reading half of the book, I decided that the book was worth translating. I hope the translation will help people who have found themself in the same situation as me (especially young people), and maybe help spread interest for the language among people with less technical knowledge. - -## Polish - -Dominik Kozaczko (dominik@kozaczko.info) has volunteered to translate the book to Polish. Translation is in progress and it's main page is available here: [Ukąś Pythona](http://python.edu.pl/byteofpython/). - -_Update_ : The translation is complete and ready as of Oct 2, 2009. Thanks to Dominik, his two students and their friend for their time and effort! - -> _Dominik Kozaczko_ - I'm a Computer Science and Information Technology teacher. - -## Portuguese - -Fidel Viegas (fidel.viegas@gmail.com) has volunteered to translate the book to Portuguese. - -## Romanian - -Paul-Sebastian Manole (brokenthorn@gmail.com) has volunteered to translate this book to Romanian. - -> _Paul-Sebastian Manole_ - I'm a second year Computer Science student at Spiru Haret University, here in Romania. I'm more of a self-taught programmer and decided to learn a new language, Python. The web told me there was no better way to do so but read ''A Byte of Python''. That's how popular this book is (congratulations to the author for writing such an easy to read book). I started liking Python so I decided to help translate the latest version of Swaroop's book in Romanian. Although I could be the one with the first initiative, I'm just one volunteer so if you can help, please join me. - -## Russian - -Vladimir Smolyar (v_2e@ukr.net) has completed a Russian translation at . - -## Ukranian - -Averkiev Andrey (averkiyev@ukr.net) has volunteered to translate the book to Russian, and perhaps Ukranian (time permitting). - -## Serbian - -"BugSpice" (amortizerka@gmail.com) has completed a Serbian translation: - -> This download link is no longer accessible. - -More details at . - -## Slovak - -Albertio Ward (albertioward@gmail.com) has translated the book to Slovak at : - -> We are a non-profit organization called "Translation for education". We represent a group of people, mainly students and professors, of the Slavonic University. Here are students from different departments: linguistics, chemistry, biology, etc. We try to find interesting publications on the Internet that can be relevant for us and our university colleagues. Sometimes we find articles by ourselves; other times our professors help us choose the material for translation. After obtaining permission from authors we translate articles and post them in our blog which is available and accessible to our colleagues and friends. These translated publications often help students in their daily study routine. - -## Spanish - -Alfonso de la Guarda Reyes (alfonsodg@ictechperu.net), Gustavo Echeverria (gustavo.echeverria@gmail.com), David Crespo Arroyo (davidcrespoarroyo@hotmail.com) and Cristian Bermudez Serna (crisbermud@hotmail.com) have volunteered to translate the book to Spanish. - -Gustavo Echeverria says: - -> I work as a software engineer in Argentina. I use mostly C# and .Net technologies at work but strictly Python or Ruby in my personal projects. I knew Python many years ago and I got stuck inmediately. Not so long after knowing Python I discovered this book and it helped me to learn the language. Then I volunteered to translate the book to Spanish. Now, after receiving some requests, I've begun to translate "A Byte of Python" with the help of Maximiliano Soler. - -Cristian Bermudez Serna says: - -> I am student of Telecommunications engineering at the University of Antioquia (Colombia). Months ago, i started to learn Python and found this wonderful book, so i volunteered to get the Spanish translation. - -## Swedish - -Mikael Jacobsson (leochingkwake@gmail.com) has volunteered to translate the book to Swedish. - -## Turkish - -Türker SEZER (tsezer@btturk.net) and Bugra Cakir (bugracakir@gmail.com) have volunteered to translate the book to Turkish. "Where is Turkish version? Bitse de okusak." diff --git a/what_next.md b/what_next.md deleted file mode 100644 index fd16c3b4..00000000 --- a/what_next.md +++ /dev/null @@ -1,148 +0,0 @@ -# What Next - -If you have read this book thoroughly till now and practiced writing a lot of programs, then you must have become comfortable and familiar with Python. You have probably created some Python programs to try out stuff and to exercise your Python skills as well. If you have not done it already, you should. The question now is 'What Next?'. - -I would suggest that you tackle this problem: - -> Create your own command-line *address-book* program using which you can browse, add, modify, delete or search for your contacts such as friends, family and colleagues and their information such as email address and/or phone number. Details must be stored for later retrieval. - -This is fairly easy if you think about it in terms of all the various stuff that we have come across till now. If you still want directions on how to proceed, then here's a hint [^1]. - -Once you are able to do this, you can claim to be a Python programmer. Now, immediately [send me an email]({{ book.contactUrl }}) thanking me for this great book ;-). This step is optional but recommended. Also, please consider [buying a printed copy]({{ book.buyBookUrl }}) to support the continued development of this book. - -If you found that program easy, here's another one: - -> Implement the [replace command](http://unixhelp.ed.ac.uk/CGI/man-cgi?replace). This command will replace one string with another in the list of files provided. - -The replace command can be as simple or as sophisticated as you wish, from simple string substitution to looking for patterns (regular expressions). - -## Next Projects - -If you found above programs easy to create, then look at this comprehensive list of projects and try writing your own programs: https://github.com/thekarangoel/Projects#numbers (the same list is also at [Martyr2's Mega Project List](http://www.dreamincode.net/forums/topic/78802-martyr2s-mega-project-ideas-list/)). - -Also see: - -- [Exercises for Programmers: 57 Challenges to Develop Your Coding Skills](https://pragprog.com/book/bhwb/exercises-for-programmers) -- [Intermediate Python Projects](https://openhatch.org/wiki/Intermediate_Python_Workshop/Projects). - -## Example Code - -The best way to learn a programming language is to write a lot of code and read a lot of code: - -- [Python Cookbook](http://code.activestate.com/recipes/langs/python/) is an extremely valuable collection of recipes or tips on how to solve certain kinds of problems using Python. This is a must-read for every Python user. -- [Python Module of the Week](http://pymotw.com/2/contents.html) is another excellent must-read guide to the [Standard Library](./stdlib.md#stdlib). - -## Advice - -- [The Hitchhiker's Guide to Python!](http://docs.python-guide.org/en/latest/) -- [The Elements of Python Style](https://github.com/amontalenti/elements-of-python-style) -- [Python Big Picture](http://slott-softwarearchitect.blogspot.ca/2013/06/python-big-picture-whats-roadmap.html) -- ["Writing Idiomatic Python" ebook](http://www.jeffknupp.com/writing-idiomatic-python-ebook/) (paid) - -## Videos - -- [Full Stack Web Development with Flask](https://github.com/realpython/discover-flask) -- [PyVideo](http://www.pyvideo.org) - -## Questions and Answers - -- [Official Python Dos and Don'ts](http://docs.python.org/3/howto/doanddont.html) -- [Official Python FAQ](http://www.python.org/doc/faq/general/) -- [Norvig's list of Infrequently Asked Questions](http://norvig.com/python-iaq.html) -- [Python Interview Q & A](http://dev.fyicenter.com/Interview-Questions/Python/index.html) -- [StackOverflow questions tagged with python](http://stackoverflow.com/questions/tagged/python) - -## Tutorials - -- [Hidden features of Python](http://stackoverflow.com/q/101268/4869) -- [What's the one code snippet/python trick/etc did you wish you knew when you learned python?](http://www.reddit.com/r/Python/comments/19dir2/whats_the_one_code_snippetpython_tricketc_did_you/) -- [Awaretek's comprehensive list of Python tutorials](http://www.awaretek.com/tutorials.html) - -## Discussion - -If you are stuck with a Python problem, and don't know whom to ask, then the [python-tutor list](http://mail.python.org/mailman/listinfo/tutor) is the best place to ask your question. - -Make sure you do your homework by trying to solving the problem yourself first and [ask smart questions](http://catb.org/~esr/faqs/smart-questions.html). - -## News - -If you want to learn what is the latest in the world of Python, then follow the [Official Python Planet](http://planet.python.org). - -## Installing libraries - -There are a huge number of open source libraries at the [Python Package Index](http://pypi.python.org/pypi) which you can use in your own programs. - -To install and use these libraries, you can use [pip](http://www.pip-installer.org/en/latest/). - -## Creating a Website - -Learn [Flask](http://flask.pocoo.org) to create your own website. Some resources to get started: - -- [Flask Official Quickstart](http://flask.pocoo.org/docs/quickstart/) -- [The Flask Mega-Tutorial](http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) -- [Example Flask Projects](https://github.com/mitsuhiko/flask/tree/master/examples) - -## Graphical Software - -Suppose you want to create your own graphical programs using Python. This can be done using a GUI (Graphical User Interface) library with their Python bindings. Bindings are what allow you to write programs in Python and use the libraries which are themselves written in C or C++ or other languages. - -There are lots of choices for GUI using Python: - -- Kivy - - http://kivy.org - -- PyGTK - - This is the Python binding for the GTK+ toolkit which is the foundation upon which GNOME is built. GTK+ has many quirks in usage but once you become comfortable, you can create GUI apps fast. The Glade graphical interface designer is indispensable. The documentation is yet to improve. GTK+ works well on GNU/Linux but its port to Windows is incomplete. You can create both free as well as proprietary software using GTK+. To get started, read the [PyGTK tutorial](http://www.pygtk.org/tutorial.html). - -- PyQt - - This is the Python binding for the Qt toolkit which is the foundation upon which the KDE is built. Qt is extremely easy to use and very powerful especially due to the Qt Designer and the amazing Qt documentation. PyQt is free if you want to create open source (GPL'ed) software and you need to buy it if you want to create proprietary closed source software. Starting with Qt 4.5 you can use it to create non-GPL software as well. To get started, read about [PySide](http://qt-project.org/wiki/PySide). - -- wxPython - - This is the Python bindings for the wxWidgets toolkit. wxPython has a learning curve associated with it. However, it is very portable and runs on GNU/Linux, Windows, Mac and even embedded platforms. There are many IDEs available for wxPython which include GUI designers as well such as [SPE (Stani's Python Editor)](http://spe.pycs.net/) and the [wxGlade](http://wxglade.sourceforge.net/) GUI builder. You can create free as well as proprietary software using wxPython. To get started, read the [wxPython tutorial](http://zetcode.com/wxpython/). - -### Summary of GUI Tools - -For more choices, see the [GuiProgramming wiki page at the official python website](http://www.python.org/cgi-bin/moinmoin/GuiProgramming). - -Unfortunately, there is no one standard GUI tool for Python. I suggest that you choose one of the above tools depending on your situation. The first factor is whether you are willing to pay to use any of the GUI tools. The second factor is whether you want the program to run only on Windows or on Mac and GNU/Linux or all of them. The third factor, if GNU/Linux is a chosen platform, is whether you are a KDE or GNOME user on GNU/Linux. - -For a more detailed and comprehensive analysis, see Page 26 of the ['The Python Papers, Volume 3, Issue 1' (PDF)](http://archive.pythonpapers.org/ThePythonPapersVolume3Issue1.pdf). - -## Various Implementations - -There are usually two parts a programming language - the language and the software. A language is _how_ you write something. The software is _what_ actually runs our programs. - -We have been using the _CPython_ software to run our programs. It is referred to as CPython because it is written in the C language and is the _Classical Python interpreter_. - -There are also other software that can run your Python programs: - -- [Jython](http://www.jython.org) - - A Python implementation that runs on the Java platform. This means you can use Java libraries and classes from within Python language and vice-versa. - -- [IronPython](http://www.codeplex.com/Wiki/View.aspx?ProjectName=IronPython) - - A Python implementation that runs on the .NET platform. This means you can use .NET libraries and classes from within Python language and vice-versa. - -- [PyPy](http://codespeak.net/pypy/dist/pypy/doc/home.html) - - A Python implementation written in Python! This is a research project to make it fast and easy to improve the interpreter since the interpreter itself is written in a dynamic language (as opposed to static languages such as C, Java or C# in the above three implementations) - -There are also others such as [CLPython](http://common-lisp.net/project/clpython/) - a Python implementation written in Common Lisp and [Brython](http://brython.info/) which is an implementation on top of a JavaScript interpreter which could mean that you can use Python (instead of JavaScript) to write your web-browser ("Ajax") programs. - -Each of these implementations have their specialized areas where they are useful. - -## Functional Programming (for advanced readers) {#functional-programming} - -When you start writing larger programs, you should definitely learn more about a functional approach to programming as opposed to the class-based approach to programming that we learned in the [object-oriented programming chapter](./oop.md#oop): - -- [Functional Programming Howto by A.M. Kuchling](http://docs.python.org/3/howto/functional.html) -- [Functional programming chapter in 'Dive Into Python' book](http://www.diveintopython.net/functional_programming/index.html) -- [Functional Programming with Python presentation](http://ua.pycon.org/static/talks/kachayev/index.html) -- [Funcy library](https://github.com/Suor/funcy) -- [PyToolz library](http://toolz.readthedocs.org/en/latest/) - -## Summary - -We have now come to the end of this book but, as they say, this is the _the beginning of the end_!. You are now an avid Python user and you are no doubt ready to solve many problems using Python. You can start automating your computer to do all kinds of previously unimaginable things or write your own games and much much more. So, get started! - ---- - -[^1]: Create a class to represent the person's information. Use a dictionary to store person objects with their name as the key. Use the pickle module to store the objects persistently on your hard disk. Use the dictionary built-in methods to add, delete and modify the persons.