首页>参考读物>计算机科学与技术>软件与程序设计

Effective Python:编写高质量Python代码的90个有效方法(原书第2版)
作者 : [美]布雷特·斯拉特金(Brett Slatkin)著
译者 : 爱飞翔 译
丛书名 : Effective系列丛书
出版日期 : 2021-01-14
ISBN : 978-7-111-67402-3
定价 : 129.00元
扩展资源下载
扩展信息
语种 : 简体中文
页数 : 388
开本 : 16
原书名 : Effective Python: 90 Specific Ways to Write Better Python, Second Edition
原出版社: Pearson Education Inc.
属性分类: 店面
包含CD : 无CD
绝版 : 未绝版
图书简介

本书可以帮你掌握真正的Pythonic编程方式,令你能够完全发挥出Python语言的强大功能,并写出健壮而高效的代码。Scott Meyers在畅销书《Effective C++》中开创了一种以使用场景为主导的精练教学方式,本书作者Brett Slatkin就以这种方式汇聚了90条实践原则、开发技巧和便捷方案,并以实用的代码范例来解释它们。
Slatkin根据自己在Google公司多年开发Python基础架构所积累的经验,揭示Python语言中一些鲜为人知的微妙特性,并给出了能够改善代码功能及运行效率的习惯用法。通过本书,你能够了解到解决关键编程任务所用的奇妙方式,并学会编写易于理解、便于维护且利于改进的代码。

图书特色

Google首席软件工程师Brett Slatkin融合自己多年实战经验,揭示Python语言中一些鲜为人知的微妙特性,并配有大量实用范例代码
新版更新至Python 3.8,基于Python的新变化对上一版进行了彻底修订,并增加了31条新的实用建议
Effective Python
90 Specific Ways to Write Better Python, Second Edition
Effective Python
编写高质量Python代码的90个有效方法
(原书第2版)
[ 美 ] 布雷特 · 斯拉特金(Brett Slatkin) 著
爱飞翔  译

图书前言

Python是一门强大的编程语言,它很有魅力,同时也很独特,所以掌握起来或许有点儿困难。许多程序员从他们熟悉的语言转到Python之后都打不开思路,所以写出来的代码没有充分发挥出Python的特性。还有一些程序员则相反,他们会滥用Python的特性,这样写出来的程序以后可能会出现严重的问题。
本书会详细地告诉大家如何采用符合Python风格的方式(Pythonic方式)来编写程序,这是使用Python语言的最佳方式。笔者假设你对这门语言已经有了初步了解。编程新手可以通过这本书学到各种Python功能的最佳用法,有经验的程序员则能够学会如何自信地运用Python中的新工具。
笔者的目标是让大家用Python开发出优秀的软件。
本书涵盖的内容
本书每一章都包含许多相互关联的条目。大家可以按照自己的需要随意阅读这些条目。每个条目都包含简洁而明确的教程,告诉你如何才能更有效率地编写Python程序。笔者在每个条目里都给出了建议,告诉大家哪些应该做,哪些应该避免,以及怎样在各种做法之间求得平衡,并且会解释笔者所选的做法好在哪里。笔者可能会在某个条目中提到其他一些条目,让大家可以全面地了解这些建议所涉及的知识。
本书第2版只针对Python 3(参见第1条),这里说的Python 3包含从3.0到3.8的各个版本。本书第1版中的许多条目仍然收录在第2版中,并且做了修订,其中有些条目改动比较大。随着Python语言越来越成熟,最佳编程方法也在演变,所以笔者在第2版中对某些问题的建议,可能与第1版的完全不同。Python 2已经在2020年1月1日退场,如果你还是主要在用这个版本来编程,那么第1版中的建议或许比第2版中的建议更加合适。
Python采用“自带电池”(batteries included)的理念来设计标准库,不像其他语言那样只提供少数几个常用的软件包,如果需要的重要功能不在这些软件包里,那就要自己去寻找了。许多Python内置软件包与Python的习惯用法有着密切的关系,所以实际上已经成了语言规范的一部分。本书篇幅有限,不可能把所有的标准模块全都讲一遍,但会涵盖其中那些需要了解和使用且用法比较关键的模块。
第1章:培养 Pythonic 思维
Python开发者社区用Pythonic这个形容词来描述具有某种特定风格的代码。这种风格是大家在使用Python语言编程并相互协作的过程中逐渐形成的。本章讲解如何采用这样的风格编写常见的Python代码。
第2章:列表与字典
在Python语言中整理信息时,最常用的方法是把一系列数值保存到列表(list)中。既然有列表,那就有另外一种跟它互补的结构,也就是字典(dict),这种结构可以把它存储的查找键映射到对应的值上。本章讲解如何采用这些数据结构来编写程序。
第3章:函数
Python中的函数具备多种特性,这有助于简化编程工作。Python函数的某些性质与其他编程语言中函数的类似,但也有一些是Python独有的。本章介绍如何使用函数来表达开发者的意图,如何让代码更容易复用,以及如何减少bug。
第4章:推导与生成
Python有一种特殊的语法,可以迅速迭代列表(list)、字典(dict)与集合(set),并据此生成相应的数据结构,这让我们能够在函数返回的这种结构上逐个访问根据原结构所派生出来的一系列值。本章讲解怎样利用这种机制来提升程序效率并降低内存用量,同时让代码变得更容易读懂。
第5章:类与接口
Python是面向对象的语言。用Python编程时,经常要编写新的类,而且还要定义这些类应该如何通过其接口以及继承体系与其他代码相交互。本章讲解怎样使用类来表达对象所应具备的行为。
第 6 章:元类与属性
元类(metaclass)与动态属性(dynamic attribute)都是很强大的Python特性,但它们也有可能会让程序出现古怪的行为与意外的效果。本章讲解这些机制的习惯用法,确保读者写出来的代码遵循最小惊讶原则(rule of least surprise)。
第7章:并发与并行
用Python很容易写并发程序,这种程序可以在同一时刻做许多件不同的事情。Python也可以通过系统调用、子进程以及C语言扩展来实现并行处理。本章介绍这些Python特性应该用在什么情况下。
第8章:稳定与性能
Python内置了一些功能与模块,可以让程序变得更加可靠。另外,Python还提供了一些工具,可以让我们轻松地提升程序的性能。本章讲解怎样用Python优化程序,让这些程序在正式的运行环境中表现得更加稳定、更加高效。
第 9 章:测试与调试
不管使用哪种语言编程,我们都应该把写出来的代码测试一下。但对于Python来说,还有个特殊的问题,那就是它所提供的动态机制可能会增加程序在运行时出现错误的风险。好在Python也让我们可以比较容易地编写测试代码和故障诊断程序。本章讲解怎样用Python内置的工具来测试并调试程序。
第 10 章:协作开发
如果许多人要协作开发一个Python程序,那就得仔细商量代码的写法了。即便你只是一个人开发,也需要了解如何使用其他人所写的模块。本章介绍标准的工具以及业界总结出来的最佳方法,告诉大家怎样协作开发Python程序。
本书使用的约定
本书采用特殊字体表示Python代码。如果某一句代码比较长,会用符号表示换行。代码中的某些部分如果跟当前要讲的主题关系不大,笔者会将这些代码删掉,并以省略号(...)表示。你可以访问“获取源代码及勘误表”部分提到的网址以获取完整的范例代码,这样就能在自己的电脑中正确地运行这些例子了。
笔者在Python风格指南的基础上做了一些修改,让范例代码便于印刷,同时还可以强调其中的重要内容。为了缩减范例代码篇幅,笔者把内嵌的文档也删去了。你在开发自己的项目时不应该这样做,而是应该遵循Python风格指南(参见第2条),并且要在源代码中撰写开发文档(参见第84条)。
书中的大部分代码伴有运行之后产生的输出。这里说的输出,是指在交互式解释器中运行这些Python程序时,控制台或终端机所打印出的信息。这些输出信息也用特殊字体表示,它们上面的那一行标着>>>符号(Python解释器的提示符)。书中使用这个符号是想告诉大家:把>>>上方的范例代码输入Python shell(Python解释器的界面)之后,会产生与>>>下方一样的输出信息。
此外,还有一些文字上方虽然没有>>>符号,但也是以特殊字体表示的。这些内容是指Python解释器之外的输出信息。这些信息的上方通常有$字符,表示这是笔者在Bash之类的命令行界面中先运行了某个程序,然后才产生这些输出的。如果你是在Windows或其他类型的操作系统中运行程序的话,那么可能要相应调整程序名称与参数。
获取源代码及勘误表
大家拿到范例代码之后,可以抛开书中讲解代码的那些内容,单独把这个完整的程序运行一遍,这是很有好处的。你可以用这些代码做实验,并试着理解程序为什么会这样运行。所有的源代码都可以从本书网站(https://effectivepython.com/)下载,书中的勘误以及提交勘误的方法,也写在这个网站里。

专家评论

“自2015年第1版出版之后,我一直在向人推荐这本书。第2版更新并补充了涉及Python 3的内容,里面写满了各种实用的Python编程技巧,这些技巧对新手和老手都有帮助。”
—Wes McKinney,Python Pandas项目创始人,Ursa Labs的主管
“如果你是从其他语言转到Python的,那就把这本书当成权威指南来看吧!它会教你怎样充分利用Python的各种特性。我用Python已经快20年了,但还是能够从这本书里发现很多有用的技巧,尤其是与Python 3的新特性有关的技巧。本书中的建议都很实用,可以帮助我们判断什么样的代码才是Python风格的代码。”
—Simon Willison,Django联合创始人
“我用Python写了很多年程序,认为自己已经很了解这门语言了,但是看过这本书中的各项技巧之后,我才发现自己写的代码仍然有很多地方可以改进。比如可以通过二分法在有序的列表中搜索,让程序跑得更快;可以采用只能通过关键字形式来指定的参数把代码写得更加清晰易读;可以通过星号表达式来拆分序列,减少出错率;可以通过zip并行迭代多个列表,让代码更具Python风格。第2版还有个好处,就是它能让我很快掌握Python 3的新特性,例如walrus操作符、f-string、typing模块等。”
—Pamela Fox,可汗学院编程课创始人
“Python 3终于成了Python的标准版本,它其实已经做了8次小的修订,其中添加了许多新特性。Brett Slatkin这次带来的Effective Python第2版,讲解了大量新的Python编程习惯,并且给出了很多条明晰的建议,这些内容考虑到了从Python 3.0到Python 3.8之间的各个版本,至于Python 2,现在可以让它歇一歇了。本书前面几章介绍了Python 3的许多新语法和新概念,比如string对象、byte对象、f-string、赋值表达式(assignment expression,作者会提到关于这种表达式的几个你不一定知道的特殊叫法),以及如何把tuple中的其他元素全都捕获下来。后面几章谈的主题比较大,其中有些内容我原来没听说过,还有一些我虽然听说过,但总找不到特别好的办法给别人讲解。比如第6章,其中有一条建议很棒,那就是第51条。另外,作者还介绍了一个奇妙的方法,叫作__init_subclass__(),我原来不太熟悉。在介绍并发与并行的章节中,第53条建议讲得很好,当然作者还讲了asyncio(异步I/O)与coroutine(协程)的问题,而且讲得很对。另外就是谈稳定与性能的那一章,其中第70条建议值得注意。总之,每一部分都写得很棒,作者把这些实践技巧讲解得相当清晰,以后我打算引用书里的一些内容,因为这些建议实在是很有道理。如果今年只读一本Python书的话,那肯定该选这一本。”
—Mike Bayer,SQLAlchemy创始人
“刚学编程的人和有经验的开发者都非常适合看这本书。书中的范例代码写得很周详,作者解释得也相当精准、透彻。第2版更新了与Python 3有关的建议,这实在是太好了。我已经用Python近20年了,但还是每看几页就能发现一些新的知识。书中给出的建议,我想每个人都应该听取。”
—Titus Brown,加州大学戴维斯分校副教授
“与上一版一样,Brett Slatkin依然很好地将整个Python开发界的各种经验,全都浓缩到了一本书中。他既谈了元类与并发这样的高端主题,也没有忘记稳定性、测试与协作开发等重要基础知识。本书新版用大家都能接受的观点,讲述了什么叫作Python式的编程风格。”
—Brandon Rhodes,python-patterns.guide的作者

上架指导

计算机/程序设计/Python

封底文字

本版针对Python 3做了更新与扩写

  用Python很容易就可以写出程序,所以这门语言特别流行,但Python独有的一些特征与表现手法却不是开发者能够轻松掌握的,而且其中还有许多陷阱,经常容易把人困住。

  本书能够帮你掌握真正的Pythonic编程方式,充分发挥Python的优势,写出健壮而高效的代码。Scott Meyers在其名著Effective C++中开创了一种用简明的场景实例来讲述编程经验的方式,本书作者Brett Slatkin也沿用这种方式,向大家讲解Python的编程原则、开发技巧与便捷方案,形成90条建议并配有实用的范例代码,以便大家能够扎实地掌握 Python 语言。

  Slatkin在Google做了多年的Python基础架构工作,根据多年的经验,他在书中指出了一些很少有人注意的问题,并告诉大家如何用相应的代码范式来提升程序的稳定程度与效率。通过本书,你会了解怎样用易于理解、易于维护且易于改进的代码来完成关键的编程任务。本版不仅增加了大量的新建议,而且还根据 Python 开发界近些年的变化,彻底修订了原书上一版中已有的建议。

本书的关键内容包括:

■ 31条新的实用建议,这些建议涵盖 Python开发的几个主要方面。

■ 对各种语句、表达式与内置类型做了详细讲解与演示。

■ 怎样写出意图清晰、便于复用而且不容易出现bug的函数。

■ 怎样更好地使用推导机制与生成器函数。

■ 怎样用类与接口准确展示相关的行为。

■ 怎样避开元类与动态属性中的一些陷阱。

■ 怎样用更高效且更清晰的方法写出并发与并行程序。

■ 怎样优化程序性能并提升代码质量。

■ 用于改进调试与测试工作的技术与内置模块。

■ 与协作开发有关的工具和经验。

译者序

一拿到这本书的英文版,立刻觉得它比上一版厚了许多。对比副书名,发现新版多出了31条建议;翻开目录,看到章节划分也和原来不同。新版单独设立了几章来强调列表与字典、推导与生成、元类与属性、稳定与性能,以及测试与调试等几个重要主题,并把上一版的一些建议从原有位置移到了这些新章中。
跟其他某些修订版本不同,本书的新版并非简单地调整文字,而是有三个重要变化。
首先,作者这次只关注Python 3,而不再兼顾Python 2,这样可以腾出许多篇幅,从而将相关技巧在Python 3中的原理与用法讲得更加透彻。
第二个变化,是作者根据Python语言近年来引入的新特性,以及Python开发界所形成的新经验,修订了上一版中的某些思路与解决方案,以便更好地发挥Python的优势。现今的Python早已从一门新兴的语言变成了获得广泛认可的成熟语言,尽管具体的特性一直在变,但依然保持着简洁而直观的编程理念。
两个版本之间的第三个区别,自然是条目上的变动。作者把已经过时或者不在本版讨论范围内的知识点从原条目里删去,并添加一些条目以突出Python的新特性。另外,作者还将某些比较笼统的条目拆分成几个新条目来详细讲解。
本版在范例代码安排上跟上一版相似,目的是让每条建议都可以单独拿出来学习并运用,所以不会以一两个大例子贯穿全书,而是针对每条建议各自举例。当然其中有些例子,比如生命游戏、生产者-消费者队列等,本身比较完备,可以用在许多场景中。但还有一些例子,则仅仅用来演示某种用法。大家应该结合自己的项目加以改编,并多做尝试。
虽然这一版在写法上延续了上一版乃至Effective系列一贯的风格,但由于内容和观点变化比较大,因此译者没有套用原来的译稿,而是重新翻译了全书。借着这次重译,我把原来措辞较为生硬的地方调整得通俗一些,便于大家理解。希望这次的新译本能够帮助更多的人了解Python语言,以及这门语言在最近几年中的变化,从而不断地更新自己的技能与思路。
我在翻译本书的过程中得到了机械工业出版社华章分社各位工作人员的帮助,在此深表感谢。特别要感谢关敏编辑再度给我机会翻译这本好书。由于时间仓促加上译者水平有限,书中可能有错误与疏漏之处,欢迎大家访问github.com/jeffreybaoshenlee/ep2-errata/issues留言,或发邮件至eastarstormlee@gmail.com,给我以批评和指教。

爱飞翔
2020年9月

图书目录

本书赞誉
译者序
前言
致谢
第1章 培养Pythonic思维 // 1
第1条 查询自己使用的Python版本 // 1
第2条 遵循PEP 8风格指南 // 2
第3条 了解bytes与str的区别 // 5
第4条 用支持插值的f-string取代C风格的格式字符串与str.format方法 // 9
第5条 用辅助函数取代复杂的表达式 // 19
第6条 把数据结构直接拆分到多个变量里,不要专门通过下标访问 // 21
第7条 尽量用enumerate取代range // 25
第8条 用zip函数同时遍历两个迭代器 // 26
第9条 不要在for与while循环后面写else块 // 28
第10条 用赋值表达式减少重复代码 // 31
第2章 列表与字典 // 37
第11条 学会对序列做切片 // 37
第12条 不要在切片里同时指定起止下标与步进 // 40
第13条 通过带星号的unpacking操作来捕获多个元素,不要用切片 // 42
第14条 用sort方法的key参数来表示复杂的排序逻辑 // 45
第15条 不要过分依赖给字典添加条目时所用的顺序 // 51
第16条 用get处理键不在字典中的情况,不要使用in与KeyError // 56
第17条 用defaultdict处理内部状态中缺失的元素,而不要用setdefault // 61
第18条 学会利用__missing__构造依赖键的默认值 // 63
第3章 函数 // 66
第19条 不要把函数返回的多个数值拆分到三个以上的变量中 // 66
第20条 遇到意外状况时应该抛出异常,不要返回None // 69
第21条 了解如何在闭包里面使用外围作用域中的变量 // 71
第22条 用数量可变的位置参数给函数设计清晰的参数列表 // 75
第23条 用关键字参数来表示可选的行为 // 77
第24条 用None和docstring来描述默认值会变的参数 // 80
第25条 用只能以关键字指定和只能按位置传入的参数来设计清晰的参数列表 // 83
第26条 用functools.wraps定义函数修饰器 // 88
第4章 推导与生成 // 91
第27条 用列表推导取代map与filter // 91
第28条 控制推导逻辑的子表达式不要超过两个 // 93
第29条 用赋值表达式消除推导中的重复代码 // 94
第30条 不要让函数直接返回列表,应该让它逐个生成列表里的值 // 97
第31条 谨慎地迭代函数所收到的参数 // 100
第32条 考虑用生成器表达式改写数据量较大的列表推导 // 104
第33条 通过yield from把多个生成器连起来用 // 106
第34条 不要用send给生成器注入数据 // 108
第35条 不要通过throw变换生成器的状态 // 113
第36条 考虑用itertools拼装迭代器与生成器 // 117
第5章 类与接口 // 122
第37条 用组合起来的类来实现多层结构,不要用嵌套的内置类型 // 122
第38条 让简单的接口接受函数,而不是类的实例 // 128
第39条 通过@classmethod多态来构造同一体系中的各类对象 // 131
第40条 通过super初始化超类 // 136
第41条 考虑用mix-in类来表示可组合的功能 // 140
第42条 优先考虑用public属性表示应受保护的数据,不要用private属性表示 // 144
第43条 自定义的容器类型应该从collections.abc继承 // 149
第6章 元类与属性 // 153
第44条 用纯属性与修饰器取代旧式的setter与getter方法 // 153
第45条 考虑用@property实现新的属性访问逻辑,不要急着重构原有的代码 // 157
第46条 用描述符来改写需要复用的@property方法 // 160
第47条 针对惰性属性使用__getattr__、__getattribute__及__setattr__ // 165
第48条 用__init_subclass__验证子类写得是否正确 // 170
第49条 用__init_subclass__记录现有的子类 // 177
第50条 用__set_name__给类属性加注解 // 181
第51条 优先考虑通过类修饰器来提供可组合的扩充功能,不要使用元类 // 185
第7章 并发与并行 // 191
第52条 用subprocess管理子进程 // 192
第53条 可以用线程执行阻塞式I/O,但不要用它做并行计算 // 195
第54条 利用Lock防止多个线程争用同一份数据 // 199
第55条 用Queue来协调各线程之间的工作进度 // 202
第56条 学会判断什么场合必须做并发 // 210
第57条 不要在每次fan-out时都新建一批Thread实例 // 214
第58条 学会正确地重构代码,以便用Queue做并发 // 218
第59条 如果必须用线程做并发,那就考虑通过ThreadPoolExecutor实现 // 224
第60条 用协程实现高并发的I/O // 226
第61条 学会用asyncio改写那些通过线程实现的I/O // 230
第62条 结合线程与协程,将代码顺利迁移到asyncio // 239
第63条 让asyncio的事件循环保持畅通,以便进一步提升程序的响应能力 // 245
第64条 考虑用concurrent.futures实现真正的并行计算 // 248
第8章 稳定与性能 // 253
第65条 合理利用try/except/else/finally结构中的每个代码块 // 253
第66条 考虑用contextlib和with语句来改写可复用的try/finally代码 // 258
第67条 用datetime模块处理本地时间,不要用time模块 // 262
第68条 用copyreg实现可靠的pickle操作 // 265
第69条 在需要准确计算的场合,用decimal表示相应的数值 // 272
第70条 先分析性能,然后再优化 // 274
第71条 优先考虑用deque实现生产者-消费者队列 // 278
第72条 考虑用bisect搜索已排序的序列 // 284
第73条 学会使用heapq制作优先级队列 // 286
第74条 考虑用memoryview与bytearray来实现无须拷贝的bytes操作 // 294
第9章 测试与调试 // 300
第75条 通过repr字符串输出调试信息 // 301
第76条 在TestCase子类里验证相关的行为 // 304
第77条 把测试前、后的准备与清理逻辑写在setUp、tearDown、setUpModule与tearDownModule中,以防用例之间互相干扰 // 309
第78条 用Mock来模拟受测代码所依赖的复杂函数 // 312
第79条 把受测代码所依赖的系统封装起来,以便于模拟和测试 // 319
第80条 考虑用pdb做交互调试 // 322
第81条 用tracemalloc来掌握内存的使用与泄漏情况 // 326
第10章 协作开发 // 329
第82条 学会寻找由其他Python开发者所构建的模块 // 329
第83条 用虚拟环境隔离项目,并重建依赖关系 // 330
第84条 每一个函数、类与模块都要写docstring // 335
第85条 用包来安排模块,以提供稳固的API // 339
第86条 考虑用模块级别的代码配置不同的部署环境 // 344
第87条 为自编的模块定义根异常,让调用者能够专门处理与此API有关的异常 // 346
第88条 用适当的方式打破循环依赖关系 // 350
第89条 重构时考虑通过warnings提醒开发者API已经发生变化 // 355
第90条 考虑通过typing做静态分析,以消除bug // 361

教学资源推荐
作者: [美]布鲁斯·埃克尔(Bruce Eckel) 戴安娜·马什(Dianne Marsh) 著
作者: (美)Richard C.Detmer
作者: Patrick Henry Winston, Sundar Narasimhan
参考读物推荐
作者: 高峰 李彬 著
作者: Francis Glassborow
作者: 邓凡平 著
作者: 宋叶志 等编著