书名:Python编程从新手到高手
ISBN:978-7-115-65974-3
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [美]贾森·C. 麦克唐纳(Jason C. McDonald)
译 周 琦 李者璈
责任编辑 龚昕岳
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
Copyright © 2023 by Jason C. McDonald. Title of English-language original Dead Simple Python: Idiomatic Python for the Impatient Programmer, ISBN 9781718500921, published by No Starch Press Inc. 245 8th Street, San Francisco, California United States 94103. The Simplified Chinese-language 1st edition copyright © 2025 by Posts & Telecom Press. All rights reserved.
本书中文简体字版由美国No Starch出版社授权人民邮电出版社出版。未经出版者书面许可,对本书任何部分不得以任何方式复制或抄袭。
版权所有,侵权必究。
本书全面细致地介绍了Python的各个功能、逻辑和惯用模式,以便读者快速编写出专业、地道、实用的Python程序,从Python新手成长为高手。
本书共5个部分。第一部分“Python环境”讲解Python的哲学、开发环境、基本语法、项目结构和代码导入等内容,为读者编写规范的Python代码奠定坚实的基础。第二部分“基本结构”讲解Python的变量、数据类型、函数、类、对象、错误和异常等。第三部分“数据和流程”讲解操作数据和控制执行流程的许多独特方法,包括集合、迭代、生成器、推导式、文本输入/输出、上下文管理、二进制和序列化等。第四部分“高级概念”探索Python的高级策略,如继承、混入、元类、抽象基类、自省、泛型、异步、并发、线程和并行等。第五部分“超越代码”讲解项目的打包、分发、调试、日志、测试和剖析等环节,并概述Python开发的方向。
本书适合想要学习编写专业Python程序的读者阅读,既可作为零基础入门Python的教材,也可作为程序员案头常备的Python工具书。本书尤其适合已掌握其他编程语言的开发者用来学习Python,可以帮助这些开发者不受其他编程语言的影响来学习地道的Python编程方法。
“Python超简单?真的吗?”
这是我首次听说本书时的反应。Python从整体上来说当然是很棒的编程语言,比其他大多数编程语言更容易理解,但编程世界中很多(其实是大多数)东西可以说和“超简单”毫无关系。
不过Jason(本书作者)随后解释了书名中使用“超简单”[1]的初衷。本书并不是一本只简单罗列一些术语介绍的“傻瓜书”,更确切地说,本书的设计目标是让读者阅读完后会说:“起初这个主题似乎很难理解,但是经过书里的解释,这个主题对我来说变得非常简单了。”在学习以及教授通用编程和Python 30多年后,我不得不说,这实在是任何形式的教学的终极目标:即便是针对棘手主题的讨论,也要把概念讲解得非常清晰。
[1] 译者注:本书英文原书名为“Dead Simple Python”,即“Python超简单”。
但这并不是本书唯一的亮点。
本书中的大量示例同样令人印象深刻。书中几乎涵盖想要编写实用的Python代码所需要的所有内容,包括变量、数据结构和循环等基础知识,以及并发和并行等高级内容。当我阅读本书时,每章都以其完备和丰富的细节给我留下了深刻印象。
那么,本书真的让Python的所有知识看起来都非常简单吗?经过多年的教学和写作,我知道我并不能代替其他任何人来回答这一问题,但我可以肯定地说:本书中的示例设计精巧,引人入胜,对概念的解释清晰易懂。这确实是一本出类拔萃的好书。
内奥米·塞德(Naomi Ceder)
Python软件基金会董事会主席
贾森·C. 麦克唐纳(Jason C. McDonald)拥有十余年软件工程经验,曾作为开发者或管理者在多家公司工作,经历过各种类型的项目,并多次在员工培训、技术会议和大学中进行软件开发、管理和职业发展等主题的演讲和教学。他还是Ubuntu社区、开放源码倡议和Python软件基金会的成员,以及DEV社区的版主。
史蒂文·宾格勒(Steven Bingler)是一位软件工程师,来自马萨诸塞州波士顿市,拥有电气工程硕士学位。他还是一名经验丰富的技术审校人员,业余时间喜欢骑自行车、攀岩,以及寻找新餐馆。
丹尼斯·波贝德里亚(Denis Pobedrya)在Libera在线聊天室中为人所熟知的ID是deniska。他熟悉Python数据结构的各种小众知识,自称“万事通”。他从事过很多工作,目前从事市场服务相关的Python后端开发工作。
瑞安· 帕洛(Ryan Palo)从机械工程师转行成为软件开发者,现在为Flashpoint编写Python代码。他拥有计算机科学(智能系统)硕士学位,喜欢分享与物理、数学、写作和代码相关的内容,他的主要输出渠道是他的博客“assert_not magic?”。他喜欢和妻子、女儿、猫、狗、各种各样的Linux设备,以及大约8把尤克里里一起待在家里。
丹尼尔· 福斯特(Daniel Foerster)出于友谊和热情承担了本书的技术审校工作。他很庆幸自己能在十几岁就遇见Python——至今为止最契合他的编程语言。在从事了多年Python相关的开发工作以及团队内外的编程教学工作之后,现在他将事业重心转向了教育领域。
西蒙· 德夫列热(Simon de Vlieger)在一些圈子里为人所熟知的ID是supakeen,他是Python社区的核心成员。作为高级程序员,他对Python、C语言和其他实验性语言感兴趣,并对软件安全具有浓厚兴趣,同时也对AVR以及其他微型嵌入式芯片非常熟悉。当前他受雇于红帽公司(Red Hat公司,知名Linux技术公司),致力于以合理且可复用的方式构建Linux。
有这样一个说法:“养育一个孩子需要一个村庄。”同样,写一本书也需要一个“村庄”。而本书的写作涉及了多个“村庄”!
Python社区成员,尤其是来自Libera在线聊天室#python频道的朋友们,他们从我第一次使用Python实现“Hello, world!”程序以来就一直在支持我,并为我提供信息和挑战。我大部分的Python知识可以追溯到那个聊天室里的朋友们,感谢他们在我写作本书的整个过程中提供的所有反馈和建议。
我非常感谢Forem和DEV社区对我的文章,尤其是构成本书框架的系列文章的热情对待。特别感谢DEV联合创始人Ben Halpern和Jess Lee以及社区经理Michael Tharrington对我的鼓励和对我的文章的推广。如果不是因为我有幸获得了知名度和积极的反馈,我永远不会考虑写这本书。
特别感谢本书严谨的技术审校团队成员Steven Bingler、Denis Pobedrya(网名deniska)、Ryan Palo、Daniel Foerster(网名pydsigner)和Simon de Vlieger(网名supakeen)。此外,Andrew Svetlov让我对不断变化的异步格局有了深刻的了解;Python Packaging Authority团队的Bernát Gábor帮助我确保本书关于封装的内容足够吸引人;Kyle Altendorf(网名altendky)教会了我基于src的项目结构的价值,并对本书面向对象编程的内容提供了反馈;James Gerity(网名SnoopJ)帮助我消除了关于多继承的内容中的歧义;Gil Gonçalves、grym和TheAssassin进行了额外的技术审校。我无法一一列举所有为本书提建议的人。一切尽在不言中。
特别感谢本书的编辑,他的热情使我有信心编写本书。
感谢我在Python社区、Ubuntu社区、MousePaw Media、Canonical及其他社区的所有朋友,尤其是Naomi Ceder、Richard Schneiderman(网名johnjohn101)、James Beecham、Laís Carvalho、Cheuk Ting Ho、Sangarshanan Veera、Raquel Dou、David Bush、John Chittum、Pat Viafore、Éric St-Jean、Chloé Smith、Jess Jang、Scott Taylor、Wilfrantz Dede、Anna Dunster、Tianlin Fu、Gerar Almonte、LinStatSDR和leaftype。每当收到你们对本书进展的询问,我都感受到了莫大的鼓舞!
最后,当然也是最重要的,我要感谢我的亲人和朋友,感谢他们无尽的支持。我的母亲Anne McDonald提供了宝贵的编辑和创意反馈,她教会了我关于写作的知识,并且从我出生起就一直在鼓励我实现梦想。感谢我最好的朋友Daniel Harrington,我们就像是互相约定并分别写出了《指环王》和《纳尼亚传奇》的Tolkien和Lewis。非常感谢我的朋友Jaime López(网名Tacoder)。感谢Bojan Miletić,他和我一样,也是The Bug Hunters Café的主持人之一,感谢他的无限热情和支持。对我亲爱的阿姨且自称我头号粉丝的Jane McArthur,以及和我一起“制造麻烦”的搭档Chris “Fox” Frasier深表爱意和感激——我非常想念他们。
Python这门语言很独特。作为一名软件开发者,我沉迷于其特殊性。编写良好的Python程序能令人感受到一种艺术美。我喜欢探寻对于一个问题最“Pythonic”(具有Python特质精神的)解决方案,然后回顾并思考是否有其他方案能获得相同效果。
遗憾的是,多年以前,我习惯于从已掌握的其他编程语言的角度来看待Python,从而陷入困境。那时,我虽然可以读、写Python代码,但无法形成那些“显而易见”的惯用编程模式。就像只能通过查阅词典来生硬地说外语一样——我虽然能编写出Python代码,但是无法真正基于Python来思考问题,我其实错失了这门语言的本质内涵。
直到我开始真正理解Python——用它来思考,我才发现这门语言的独特之处。解决方案变得显而易见。设计方案变成一种乐趣,而不是一个谜团。
当一位新程序员开始尝试使用Python时,他几乎没有先入为主的偏见,因为没有其他编程语言作为“母语”来干扰他对Python的探索。但是对于将Python作为第二甚至第三语言的老程序员,思想上的转变在某些方面要艰难得多——他们不仅必须学习新知识,而且在很多方面必须忘掉旧知识(这尤其困难)。
本书正是这一艰难旅程的最佳指南。
本书适合想要学习编写专业Python程序的读者阅读,无论是零编程基础的读者,还是已掌握其他编程语言的开发者。本书特别关注如何以“Pythonic”方式来完成任务,可以帮助读者不受其他编程语言的影响来学习地道的Python编程方法。
如果你是一位中级Python开发者,一样能发现本书很有用。尽管我使用Python很多年了,但是对其中的一些主题,我直到最近才突然感到豁然开朗。本书包含了对这些主题的解释。
本书的所有主题,乍一看可能都不简单。读者可能也会怀疑,这么厚的书,怎么可能“简单”?
我为本书起名为“Python超简单”[1],其实是想描述读者阅读完本书后的体验,而不是读之前的期待。我们应该认识到,任何值得学习的主题,在初次接触时,都会令人感觉不可逾越。同样,任何概念如果值得向一名软件开发者阐述,都必须具备足够的深度,以致丧失“简单”这种先验性标签。
[1] 译者注:本书英文原书名为“Dead Simple Python”,即“Python超简单”。
本书的目标是让读者在阅读完每章后,无论这章的主题最初看起来多么复杂,都能不禁感叹:这些内容其实是显而易见的,实际上“超简单”!此时,读者就可以像使用母语一般自然地使用Python进行思考。
为了帮助读者达到这种理解程度,本书通常从各主题的最基础、最明确的形式开始:先确立一个基点,再一层层叠加,最终形成惯用模式。本书希望通过这种方式,让读者精确又舒适地理解Python每个功能的由来以及惯用模式。
本书共5个部分。和其他面向初学者的图书不同,本书假定读者想尽快开始编写代码,且编写出的代码能达到产品级质量(而不是特别简单的示例代码)。本书需要读者事先完成一些初步工作,这样可以确保读者更容易地将新知识应用到实际项目中,并获得反馈。
第一部分“Python环境”(第1~4章)让读者首先掌握Python的基础知识,包括Python的哲学、开发环境、基本语法、项目结构和代码导入。这将为读者编写产品级代码奠定坚实的基础。
第二部分“基本结构”(第5~8章)探索Python的变量、数据类型、函数、类、对象、错误和异常等基本结构,并讲解如何充分利用它们。
第三部分“数据和流程”(第9~12章)介绍操作数据和控制执行流程的许多独特方法,包括集合、迭代、生成器、推导式、文本输入/输出、上下文管理、二进制和序列化等。
第四部分“高级概念”(第13~17章)揭示各种可以令读者编写出更强大的代码的高级策略,包含继承、混入、元类、抽象基类、自省、泛型、异步、并发、线程和并行等。这些正是以往多数课程和图书中略过的各种“可怕”主题。
第五部分“超越代码”(第18~21章)讲解实际项目的打包、分发、调试、日志、测试和剖析等内容,并介绍各种值得探索的Python应用方向。
本书不会过多重复编程的基本概念,例如(从一个与编程语言种类无关的角度来看)什么是变量和函数,以及类和对象之间的区别是什么等。本书仅简要定义一些必要概念,即那些在编程世界中并不普遍存在的概念。
本书并不想对Python相关主题进行详尽无遗的讨论,而是更多关注原因和方法,以帮助读者构建坚实的基础。本书鼓励读者通过额外查阅资料来拓展理解,如通过查阅官方文档了解库函数等概念。对于标准库中很多流行的功能,比如随机数和日期/时间操作等,本书在示例中调用时仅稍作解释。
为了控制本书的探讨范畴,本书不会涉及太多第三方工具和库。虽然我经常被要求讨论Python中默认工具的各种流行替代方案,但由于这些替代方案总是会像季节更替般从“流行”快速变得“失宠”,因此我建议使用默认方案。当然,有零星意外,但仅限于那种在Python生态中无所不在,甚至让标准库黯然失色的第三方工具。
一般来说,如果某个第三方工具特别值得关注,本书会向读者推荐其官方网站和官方文档。
本书的目标是成为一本实操手册,建议读者从头按顺序阅读各章。无论是Python新手,还是已经尝试过一段时间却感觉没有掌握要领的Python用户,都可以从本书中填补许多从未意识到的知识空白。
当然,如果想立即理解某个特定主题,可以直接跳到对应章节开始探索。多数章节其实是独立编撰而成的,但本书始终默认读者已经阅读并理解了前置章节的所有内容。
几乎所有Python图书或在线文章都从其他编程语言借用词汇,比如元素、变量等。虽然通常认为这样能有效将Python概念和读者现有知识关联起来,但我认为这种词汇借用最终将适得其反。如果基于其他语言来理解Python,是无法写出清晰、符合Python惯用模式的代码的。更重要的是,如果读者习惯使用不规范的词汇,就会发现官方文档难以阅读。
因此,本书坚持使用官方词汇。已出版图书中坚持这一立场的非常少,本书很自豪能成为其中之一。毕竟,想成为当地人,就必须学会使用当地语言。
如果基于读者已掌握的语言,那么读者的理论库中总是可能存在一些盲区。比如,Haskell开发者可能不熟悉面向对象编程,C++程序员可能不熟悉函数式编程。
为了消除这些隔阂,本书偶尔会提供理论概述,简要阐述与某些编程范式、模式相关的基本理论和最佳实践。所以,如果读者已经懂得某个特定概念,可以跳过对应的理论概述,直接学习Python领域的特定内容。
其实,从一本技术书中彻底清除个人观点几乎是不可能的,尤其是像本书这样专注于探讨惯用法的书。不过,我认为自己已经尽了最大努力来保持客观。
本书不是我的个人作品,而是从Python社区提炼出的集体智慧的结晶。本书经历了两年的激烈辩论,以及研究、实践,我自身的开发习惯也发生了巨大变化。开始创作本书时的我和现在的我,可以认为完全不是同一个Python开发者了。
即便如此,任何一本书也不可能让所有人满意。有时,我不得不在正文中特别提到从未达成满意结论的辩论。即使那些我认为已经圆满解决的主题,也可能引发另一些Python开发者的强烈负面反应。事实上,其中有些争论也激起过我自身的强烈反应,直到我真正理解了它们。
所以我建议大家以开放的心态阅读本书,即使你自认为早已相当熟悉编程和Python。我在本书中尽力解释了所有建议背后的理由,也同样鼓励读者在采纳任何建议时能以相同的认真程度进行思考。
本书中的大部分示例代码是我仔细构建而成的,以便展示对应主题是如何实现的。在大多数情况下,我会故意复杂化示例,以强调其他教程经常忽略的问题和意外。对于复杂化的示例,我会指出来,但同时,我也可能会简化或绕开与当前主题无关的部分。
因此,本书中的示例代码通常比其他教程中的示例代码更长,章节篇幅看起来也更长。不用因页数太多而感到气馁,一章一章地学习就好。
除非另行说明,书中所有示例都可运行,或者以可预见的方式运行失败。所有代码始终遵守Python风格约定。强烈建议读者亲手输入每个示例的代码并运行[2]。
[2] 译者注:但不要只是简单地输入,看到正确输出就觉得大功告成了,这只是探索的开始,只有仔细推敲每行代码,并最终理解其含义,才能有收获。
我努力对Python代码段进行了标注,并将其保存为可运行的示例。我给出了文件名,并对代码段进行编号(:1、:2,以此类推)。当代码被修改时,为代码编号追加字母,比如2b意味着是对代码段2a的改进,而修改的部分将被加粗。
有人问过我,为什么没在书中提供一个完整的综合项目?答案很简单:本书假定读者已有自己想开发的Python项目,所以本书不会提供另外一个项目来分散读者的注意力,而是专注于展示可以直接用于读者项目的各种工具或方法。
如果读者还没有自己的项目,这正是开始的好时机,开始构建你人生中的第一个项目吧!想想你希望得到哪个问题的解决方案(或更好的解决方案),然后开始构建相应的项目。从问题的一小部分开始就好。创建第一个项目并无魔法,只需让其成为你真正会使用的工具即可。别用“完美”来要求你的第一次尝试。技术社区中有过断言:“你总是会抛弃第一个。”所以一开始不用害怕哪儿构建错了!本书专注于为你提供通向成功的工具。
当然,如果开发一个项目对你而言尚有难度,那么可以先认真完成本书中给出的各项示例。
任何情况下,都强烈建议你创建一个自己的“靶场”[3]项目,在一个安全环境中开始尝试Python,这样就不用担心你的破坏性行为会对其他环境造成损害。本书将在第2章和第3章介绍Python代码的运行,并在第4章介绍Python项目的结构。在第18章讨论实际项目的打包和分发时,将重新讨论Python项目的结构。
[3] 译者注:“靶场”指的是虚拟环境。Python早已融入所有操作系统,千万不要轻易用sudo等类似指令对系统本身的Python环境进行变更,使用合理的Python虚拟运行时可将私人项目和系统环境隔离。个人推荐使用Miniconda来构建Python虚拟环境。
● 读者应已掌握编程的基本要点。本书教授的是Python而不是编程[4]。
[4] 译者注:更准确地讲,本书教授的是Python的工程实践方法。
● 读者应有可操作的计算机,能运行Python 3.7或更高版本。如果还没安装Python,不用担心,第2章将进行介绍。
● 读者应了解如何在计算机上使用命令行及相关基础命令,尤其是相对路径和绝对路径,以及导航文件系统。如果还不知道这些,建议先学习一下再来阅读本书。
● 读者应该有稳定的互联网连接(即便不够快),以支持文档查阅和偶尔进行包的下载。当然,书中示例已尽可能设计成没有互联网也可以工作。
现在,去准备一杯你最爱喝的饮料,拿好笔记本和笔,在计算机前坐稳,让我们开始吧!
本书提供如下资源:
● 本书源代码;
● 本书学习思维导图;
● 程序员面试手册电子书;
● 异步社区7天VIP会员。
要获得以上资源,您可以扫描下方二维码,根据指引领取。
作译者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区(https://www.epubit.com),按书名搜索,进入本书页面,单击“发表勘误”,输入您发现的错误信息,然后单击“提交勘误”按钮即可(见下页图)。本书的作译者和编辑会对您提交的错误信息进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线投稿(直接访问www.epubit.com/ selfpublish/submission即可)。
如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发送给我们。您的这一举动是对作译者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作译者与读者的在线交流互动,以及传统出版与数字出版的融合发展。
“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域30余年的发展与积淀。异步图书面向IT行业及各行业使用IT的用户。
我一直秉持这样一个观点:最好的学习Python的路径并不是从语言本身开始,而是从Python的哲学开始。要写出好的Python代码,必须先理解Python是什么。这就是本章的重点。
Python是由荷兰程序员Guido van Rossum创造的一门编程语言,于1991年发布。Python这个名字并不是指蟒蛇,而是指电视节目Monty Python’s Flying Circus(这一点本身就能告诉你很多关于这门语言的思想)。这个项目最初是一个业余项目,但现在已经成为最受欢迎的计算机语言之一。
从技术角度来看,Python是一门高级的通用编程语言,它支持过程式编程、面向对象编程和函数式编程等编程范式。
Python爱好者总是喜欢强调它的可读性和简洁性,这让人们在初次接触Python时有一种“魔法”的感觉。这也导致出现了一些对新手来说并不是很有用的建议:“Python很简单,它就是伪代码!”
这并不是完全正确的。不要让Python的自然可读性欺骗了你:Python确实很独特,受到了很多其他语言的影响,但它往往和其他语言没有太多相似之处。要真正掌握它,你必须从它本身开始,而不是用它和其他语言进行深入比较。这正是本书要做的事情。
最重要的是,Python是一种信念。这种信念由一群不同背景的极客构筑,他们之所以能够这么做,只是因为他们对于构建一门优秀的编程语言有着大胆的想法。当你真正理解Python时,它就会改变你的整个视角。你是这个信念的一部分,这个信念已经有了自己的生命。
正如Guido van Rossum在他著名的“国王节演讲”(King’s Day Speech,详见附录C)中所说的那样:
我认为最重要的想法是,Python是在互联网上开发的,完全开放,由一群志愿者(但并非业余人士!)开发,他们对这门语言充满了激情和主人翁精神。
人们对Python有很多的误解,其中一些误解导致人们在某些应用场景下想方设法避免使用Python,甚至完全不使用Python。
在我看来,“脚本语言”是讨论编程语言时最令人讨厌的术语之一。它暗示着这门语言不适合编写“真正”的软件(见误解5)。
Python是一门图灵完备的语言,这意味着你可以用Python实现任何其他编程语言,然后就可以执行用那种语言编写的任何程序。
换句话说,任何其他编程语言能做的事情,Python都能做到。这是否容易,乃至于是否可行,取决于你想要做什么。
通常来说,人们很容易认为,像Python这样更高级的或解释型编程语言比C语言这样更低级的或编译型编程语言慢。事实上,这取决于语言的实现方式和使用方式。在本书中,我们将介绍几个与提升Python代码性能相关的概念。
Python解释器的默认实现CPython是用C语言写的,在执行效率上的确会比原生机器码低。然而,有各种各样的库、技术以及其他Python解释器的实现(包括PyPy),它们的整体性能都要好得多(参见第21章),甚至接近原生机器码的执行效率。
综上所述,你应该弄明白性能是如何影响你的项目的。在大多数情况下,Python的性能已经足够好,可以作为应用开发、数据分析、科学计算、游戏开发、Web开发等领域的首选语言。CPython的性能缺陷通常只会在你面对一些特定的、对性能要求极高的场景时才会成为问题。即使如此,也有办法解决这些问题。对大多数项目来说,Python的基本性能已经足够了。
Python是一门“解释型语言”,这意味着代码在运行时由语言的解释器读取、解释和执行。运行Python项目的最终用户通常需要安装Python解释器。
与之对应的是所谓的“汇编型语言”,比如C语言、C++和FORTRAN。在这些语言中,编译的最终结果是机器码,可以直接在任何兼容的计算机上执行,而不需要安装其他程序(或者将其与代码捆绑在一起)。
有关“编译型语言”这个术语的争议非常多,这就是为什么我喜欢使用“解释型语言”和“汇编型语言”两个术语来区分它们。实际上相关的争论可以说是个无底洞。
很多开发者认为Python代码不能编译成机器码,这似乎是显而易见的结论。事实上,Python代码可以编译成机器码,尽管这种情况很少见。
如果你想尝试一下这条路径,那么这里有几个选项。在UNIX系统中,内置的Freeze工具可将Python字节码转换为C语言数组,然后将这些C语言代码汇编为机器码。但是这并不会产生真正的汇编Python代码,因为Python解释器仍然需要在幕后被调用。Freeze只能在UNIX系统中工作。cx_Freeze工具以及Windows系统中的py2exe所做的事,与Freeze类似。
想要真正地将Python代码编译为机器码,你必须使用中间语言。Nuitka可以用于将Python代码转换为C语言或C++代码,然后将其汇编为机器码。你也可以使用VOC将Python代码转换为Java代码。Cython则允许将特殊形式的Python代码转换为C语言代码,尽管它主要面向用C语言编写Python扩展。
Python解释器会将原始代码编译为稍后执行所需的字节码。解释器包含一个虚拟机,它会像CPU执行机器码一样执行Python字节码。有时,出于性能上的考虑,解释器会提前将代码转换为字节码,并生成包含字节码的 .pyc文件。虽然这在某种意义上是“编译”,但将代码编译为字节码与将代码编译为机器码之间存在一个关键区别:字节码仍然需要通过解释器执行,而机器码可以直接执行,不需要额外的程序。(从技术上讲,“编译”为机器码称为汇编,尽管这种区别往往被忽略或忽视。)
在实践中,大多数Python项目以源代码或Python字节码的形式分发,这些代码在安装于用户计算机上的Python解释器中运行。有时,以标准的可执行文件的方式进行分发更为可取,例如在终端用户计算机上安装或在闭源项目中安装。对于这些情况,Python社区提供了PyInstaller和cx_Freeze等工具。这些工具不会编译代码,而是将Python源代码或字节码与解释器捆绑在一起,以便独立执行(请参阅第18章)。
我经常听一些开发者说:“如果能将整个项目都放在一个文件中,那么Python就很有用。”这种“吐槽”通常基于这样的误解:具有多个文件的Python项目结构令人头大[1]。这确实是趋势,但只是因为很少有开发者知道如何正确地构建Python项目。
[1] 译者注:Python擅长把大项目变成多个简单的“小项目”,所以看起来“没有大项目”。
实际上,Python项目的结构比C++和Java项目的结构要简单得多。一旦开发者理解了包、模块和导入系统(请参阅第4章)的概念,就可以轻松处理多个代码文件。
这个误解的存在还有另外一个原因:Python是动态类型的,而不像Java或C++那样是静态类型的,一些人认为这使得重构变得更加困难。实际上,如果开发者知道如何使用Python的类型系统,而不是与之抗争,这就不是问题(请参阅第5章)。
过去很多年里,Python存在两个主要版本。从2001年开始,Python 2是标准版本,这意味着大多数关于Python的图书和文章都是为这个版本写的。Python 2的最后一个版本是Python 2.7。
现在的主线版本是Python 3,开发时称为Python 3000或Py3k。从2008年年末发布Python 3到2019年,我们处于Python 2和Python 3两个主要版本之间:许多现有的代码和包都是用Python 2编写的,而Python 3则被越来越多地推荐用于不需要支持Python旧版本的新项目。许多技术和工具都存在兼容Python 2和Python 3的代码,这有助于当时许多项目的过渡。
但最近几年,尤其是Python 3.5发布后,我们开始完全摆脱Python 2。大多数主要的库支持Python 3,而对Python旧版本的支持则变得不那么重要。
2020年1月1日,Python 2正式停止维护,Python 3成为标准版本。Python 4目前仍然只是一个模糊的传闻,所以可以肯定的是,Python 3将会在未来几年一直存在。
遗憾的是,许多软件开发团队将代码从Python 2迁移到Python 3的速度很慢(有时是不可避免的),这使许多项目陷入了困境。如果你在专业领域使用Python,那么你很有可能需要协助将一些代码迁移到Python 3。Python的标准库包含一个名为2to3的工具,它可以帮助你自动化这个过程。将代码通过这个工具运行是很好的第一步,但是你仍然需要手动更新代码以使用Python 3提供的一些新模式和工具。
作为一个Python开发者,你可能无数次地听到关于Pythonic代码的讨论,究竟什么是Pythonic代码呢?通常来说,能较好利用语言本身功能的惯用代码被认为是Pythonic代码。
遗憾的是,这非常容易被过度演绎。因此,Python中最佳实践的话题在社区中经常引发激烈的争论。不要因此而惊慌。通过经常与我们自己的习惯和标准进行斗争,我们将不断改进它们和我们自己的理解。
我们在Python中讨论最佳实践的倾向源于我们的哲学,即“只有一种方法可以做到这一点”(There’s Only One Way To Do It,TOOWTDI),这句话是PythonLabs在2000年提出的,作为对Perl社区的格言“有多种方法可以做到这一点”(There’s More Than One Way To Do It,TMTOWTDI)的一种讽刺性回应。尽管这些社区之间存在历史性对抗,但这些哲学并不严格相反。
Python开发者们很有理由相信,对于任何特定问题,都有单一的、可量化的“最佳”解决方案。我们的任务是找出这个解决方案,但我们也知道我们往往会远远落后于目标。通过进行持续的讨论、争论和实验,我们不断改进我们的方法,以追求理论上的最佳解决方案。
同样,Perl社区明白很难一次性地给出最佳解决方案,因此他们强调实验而不是遵守严格的标准,以努力发现更好的解决方案。
最终,我们所有人的目标都是一致的:定义出最好的解决方案。只不过我们各自有着不同的重点。
在本书中,我将重点介绍已广泛接受的编写代码的Pythonic方法。但我不认为自己是最终的权威,Python社区的同行们始终有很多东西可以添加到这些讨论中,我将会持续不停地从他们那里学习新的东西!
1999年,Python官方邮件列表上开始了一场关于编写一些通用化的指导原则的讨论。Tim Peters是社区的一位突出成员,他玩笑式地以类似于诗歌的方式提出了19条原则作为大纲,并留下了第20个位置请Guido van Rossum来完成(但他从未完成过)。
其余的社区成员很快就把这个总结视为对Python哲学的一个很好的概述,最终将其整体作为Python之禅(The Zen of Python)。整个文本则作为PEP 20由Python官方发布。
这些原则如下[2]。
[2] 译者注:从2005年开始,Python中国社区翻译迭代了十多版Python之禅,目前这个版本的主要贡献者是《编写高质量代码:改善Python程序的91个建议》的作者赖勇浩。
优雅好过丑陋。
显式好过隐式。
简单好过复合。
复合好过复杂。
扁平好过嵌套。
稀疏好过密集。
可读性很重要。
即使要为了实用性而牺牲纯粹性,
特例也并不特殊到足以破坏规则。
不应悄悄放过错误,
除非确定需要这样。
面对太多可能,不要尝试猜测。
应该有一种(且最好只有一种)明显的方式来做到这一点。
虽然这并不容易,毕竟你不是那位荷兰人[3]。
[3] 译者注:“那位荷兰人”指的是Python的创造者Guido van Rossum,他是荷兰人。
虽然一直不做总是要好过匆忙去做,
但是现在就做还是要好过永远不做。
若实现方案很难解释,那它肯定不是个好方案;
若实现方案很好解释,那它有可能是个好方案。
命名空间是个绝妙想法——我们应该多使用它!
这些原则是开放的,可以解释为不同的意思,有些人甚至认为Tim Peters在写Python之禅时是在开玩笑。但是在这个过程中,我学到了一个很重要的道理,那就是对Python开发者而言,“开玩笑”和“认真”之间的界限是非常细微的。
在任何情况下,Python之禅都是讨论Python最佳实践的好地方,许多开发者(包括我自己)经常会回到这里。在本书中,我也会经常提到它。
本书的目的是成为你学习Python的起点,而不是终点。一旦你熟悉了Python,你就可以转到Python官方文档,了解更多关于特定功能或工具的知识。
Python中的任何新功能都是从Python增强提案(Python Enhancement Proposal,PEP)开始的。每个PEP都有唯一的编号,并已发布到官方PEP索引中。一旦提出了PEP,它就会被考虑、讨论,最终被接受或拒绝。
一个PEP被接受后,它就是文档的一部分,因为它们是定义Python功能的最具凝聚力和权威性的描述。此外,还有几个元PEP(Meta-PEP)和信息PEP(Informational PEP),它们为Python社区和语言提供了支撑。
因此,如果你有任何关于Python的问题,官方文档和PEP索引应该是你首先要去的地方。在本书中,我也会经常提到它们。
为了理解语言是如何演变的,以及为什么会演变,了解谁在掌控很重要。当一个PEP被提出时,谁来决定它是被接受还是被拒绝?
Python是一个归属于非营利性组织——Python软件基金会的开源项目。与许多其他流行的语言不同,Python和任何营利性组织之间没有正式的关联。
作为一个开源项目,Python受到活跃而充满活力的社区的支持。核心团队由一群维护语言和让社区运行得更加顺畅的可信的志愿者构成。
Python的创造者Guido van Rossum过去是“仁慈的终身独裁者”(Benevolent Dictator for Life,BDFL),他对所有PEP进行最终决策,并监督Python的持续发展。2018年,他决定不再担任这个角色。
在他退休后,PEP 13被创建,以建立新的治理系统。现在,Python语言由核心团队选举出的5人领导小组来管理。每次Python的新版本发布时,都会选出新的领导小组。
Python社区(Python Community)庞大且多样化,由来自世界各地的人构成,他们都因对这种独特的语言的热爱而团结在一起。自从我多年前作为一个完全的新手偶然发现这个社区以来,我从中获得了无法估量的帮助、指导和灵感。我也很荣幸能够为他人提供同样的帮助。如果没有Python社区朋友们的不断反馈,本书就不会面世!
Python社区由核心团队主持,依据Python行为准则来管理。简而言之,Python社区强调开放、体贴和尊重的行为,总结如下。
总的来说,我们彼此尊重。我们之所以为这个社区做出贡献,是因为我们想要做出自己的贡献,而不是有人强迫我们。如果我们记住这一点,这些准则就会自然而然地出现。
我强烈推荐任何使用Python的开发者加入这个活跃的社区。参与其中的最好方法之一是通过Libera在线聊天室的#python频道。你可以在Python官网的Community页面找到进入Libera在线聊天室的指南。
如果你对Python有任何问题(包括在阅读本书时),我建议你到Libera在线聊天室的#python频道寻求帮助。你很有可能在那里遇到我和本书大部分的技术审校团队成员。
在第21章,我将从多个方面讨论Python社区。
Python的口号“只有一种方式”,一开始可能会让人感到困惑。解决任何一个问题都有很多种可能的方法,Python爱好者们是对自己的想法太着迷了吗?
幸运的是,不是这样的。这个口号意味着更加鼓舞人心的东西,这也是每一个Python开发者都应该理解的。
一些观点来自Python之禅,其中包括如下两个相当神秘的句子。
应该有一种(且最好只有一种)明显的方式来做到这一点。
虽然这并不容易,毕竟你不是那位荷兰人。
Tim Peters当然是在调侃Python的创造者Guido van Rossum——他是荷兰人。作为Python的创造者,Guido可以很容易地找到解决Python问题的“明显的方式”,尤其是在早期。
“明显的方式”(obvious way)是Python的一个术语,用于描述“最佳解决方案”——良好的实践、干净的风格和合理的效率的结合,使得代码即使对于学习Python的新手也是易于理解的。
问题的细节通常会影响这种“明显的方式”:一种情况可能需要循环,另一种可能需要递归,还有一种可能需要列表推导式。与通常意义上的“明显”相反,解决方案通常并不简单。最佳解决方案只有在你知道它之后才会显而易见,而怎么到达这一点是最棘手的。
然而,对“明显的方式”的追求是Python社区的一个定义性特征,它对本书产生了深远的影响。书中的很多见解都是在我和我的Python爱好者同行之间进行的激烈辩论中产生的。因此,我从那些常常与我争论技术细节的同行中挑选出了我的技术审校团队成员,而且他们经常彼此对立。
任何最终被认为是解决问题的“正确方式”的方案通常都是因为其技术优势才被接受的,而不是因为Python开发者之间的一些类似的偏见,这些开发者是我曾经有幸合作的最严格的人。这种逻辑的方法溢出到了我们每一次的对话中(这导致一些非常惊人和具有启发性的学术辩论)。
新的情况会不断出现。在任何Python开发者的职业生涯中,编码永远不会变得真正“简单”。每个项目中都会出现需要仔细考虑的情况,而且通常还会有争论。开发者必须尝试以对他们来说最明显的方式解决问题,然后将解决方案提交给同行进行评审。
在我看来,本书中的方法在很多情况下都是最明显的,大多数得到了我的同行们的支持,但我敢肯定的是,我在Python方面差了Guido van Rossum很多。如果你发现自己在Python社区中争论技术,那么请不要把本书举在任何人的面前,作为你的解决方案最好的证据!找到明显的解决方案的技能是不可教的,只能通过实践来学习。
尽管多年来有许多关于Python的传言,但Python是一种多功能且技术上可靠的语言,几乎可以处理你抛出的任何问题。无论你是编写自动化脚本、处理大型数据集、构建本地用户应用程序、实现机器学习,还是制作Web应用程序和应用程序接口(Application Program Interface,API),Python都是一个可靠的选择。最重要的是,Python有一个活跃、多样化和能提供帮助的社区。
成功的关键是编写Python代码,以充分利用Python的优点和功能。目标不仅仅是编写能工作的代码,而是编写优雅的代码。本书接下来的部分将教你如何做到这一点。