- Preface 前言
- 第1章 引论
- 第2章 编程惯用法
- 第3章 基础语法
- 建议19:有节制地使用 from…import 语句
- 建议20:优先使用 absolute import 来导入模块
- 建议21:i+=1 不等于 ++i
- 建议22:使用 with 自动关闭资源
- 建议23:使用 else 子句简化循环(异常处理)
- 建议24:遵循异常处理的几点基本原则
- 建议25:避免 finally 中可能发生的陷阱
- 建议26:深入理解 None 正确判断对象是否为空
- 建议27:连接字符串应优先使用 join 而不是 +
- 建议28:格式化字符串时尽量使用 .format 方式而不是 %
- 建议29:区别对待可变对象和不可变对象
- 建议30:[]、() 和 {}:一致的容器初始化形式
- 建议31:记住函数传参既不是传值也不是传引用
- 建议32:警惕默认参数潜在的问题
- 建议33:慎用变长参数
- 建议34:深入理解 str() 和 repr() 的区别
- 建议35:分清 staticmethod 和 classmethod 的适用场景
- 第4章 库
- 建议36:掌握字符串的基本用法
- 建议37:按需选择 sort() 或者 sorted()
- 建议38:使用 copy 模块深拷贝对象
- 建议39:使用 Counter 进行计数统计
- 建议40:深入掌握 ConfigParser
- 建议41:使用 argparse 处理命令行参数
- 建议42:使用 pandas 处理大型 CSV 文件
- 建议43:一般情况使用 ElementTree 解析 XML
- 建议44:理解模块 pickle 优劣
- 建议45:序列化的另一个不错的选择 JSON
- 建议46:使用 traceback 获取栈信息
- 建议47:使用 logging 记录日志信息
- 建议48:使用 threading 模块编写多线程程序
- 建议49:使用 Queue 使多线程编程更安全
- 第5章 设计模式
- 第6章 内部机制
- 建议54:理解 built-in objects
- 建议55:init() 不是构造方法
- 建议56:理解名字查找机制
- 建议57:为什么需要 self 参数
- 建议58:理解 MRO 与多继承
- 建议59:理解描述符机制
- 建议60:区别 getattr() 和 getattribute() 方法
- 建议61:使用更为安全的 property
- 建议62:掌握 metaclass
- 建议63:熟悉 Python 对象协议
- 建议64:利用操作符重载实现中缀语法
- 建议65:熟悉 Python 的迭代器协议
- 建议66:熟悉 Python 的生成器
- 建议67:基于生成器的协程及 greenlet
- 建议68:理解 GIL 的局限性
- 建议69:对象的管理与垃圾回收
- 第7章 使用工具辅助项目开发
- 第8章 性能剖析与优化
建议2:编写 Pythonic 代码
如何编写更加Pythonic的代码,与定义什么是Pythonic一样困难。在这里,只能给出一些经验之谈,希望对大家有所帮助。
(1)要避免劣化代码
与优化代码对应,劣化代码就是一开始写出来就是不合理的代码,比如不合适的变量命名等。通常有以下几个值得注意的地方:
1)避免只用大小写来区分不同的对象。如a是一个数值类型变量,A是String类型,虽然在编码过程中很容易区分二者的含义,但这样做毫无益处,它不会给其他阅读代码的人带来多少便利。
2)避免使用容易引起混淆的名称。容易引起混淆的名称的使用情形包括:重复使用已经存在于上下文中的变量名来表示不同的类型;误用了内建名称来表示其他含义的名称而使之在当前命名空间被屏蔽;没有构建新的数据类型的情况下使用类似于element、list、dict等作为变量名;使用o(字母O小写的形式,容易与数值0混淆)、l(字母L小写的形式,容易与数值1混淆)等作为变量名。因此推荐变量名与所要解决的问题域一致。有如下两个示例,示例二比示例一更好。
示例一:
>>> def funA(list,num): ... for element in list: ... if num==element: ... return True ... else: ... pass ...
示例二:
>>> def find_num(searchList,num): ... for listValue in searchList: ... if num==listValue: ... return True ... else: ... pass ...
3)不要害怕过长的变量名。为了使程序更容易理解和阅读,有的时候长变量名是必要的。不要为了少写几个字母而过分缩写。下例是一个用来保存用户信息的字典结构,变量名person_info比pi的可读性要强得多。
>>> person_info={'name':'Jon','IDCard':'200304','address':'Num203,Monday Road', 'email':'test@gail.com'}
(2)深入认识Python有助于编写Pythonic代码
可以从以下几个方面进行着手:
全面掌握Python提供给我们的所有特性,包括语言特性和库特性。其中最好的学习方式应该是通读官方手册中的Language Reference和Library Reference。掌握了语言特性和库特性,以后许多“惯用法”自然而然就掌握了,写代码的时候,自然会使用常见的、公认的、简短的惯用法来实现预期效果,也使得代码显得尤为Pythonic。
随着Python的版本更新、时间的推移,Python语言不断演进,社区不断成长,还需要学习每个Python新版本提供的新特性,以及掌握它的变化趋势。从另一角度来看,一方面Python语言推荐使用大量的惯用法来完成任务(“完成任务的唯一方法”);另一方面,社区不断演变的新惯用法反过来又影响了语言的进化,以更好地支持惯用法。比如早年的Pythonista常用dict.has_key()方法来判断字典对象是否包含某个元素,但新版本的Python中提供了in操作符(支持多种容器类型)取代它。改变习惯的阻力很大,而克服这些阻力的唯一方法就是加深对Python的认识,因为在语言支持正确的惯用法之后,非推荐的代码通常执行起来更慢。所以说,不更新知识是不行的。
深入学习业界公认的比较Pythonic的代码,比如Flask、gevent和requests等。以requests这个通过HTTP(HTTPS)协议获取网络资源的程序库为例,要获取带有Basic Auth的网络资源时,代码如下:
import requests r = requests.get('https://api.github.com', auth=('user', 'pass')) print r.status_code print r.headers['content-type'] # ------ # 200 # 'application/json'
而使用Python标准库httplib2时,代码就非常复杂,程序员需要了解相当多的关于HTTP协议和Basic Auth的知识才能编程。
import urllib2gh_url = 'https://api.github.com' req = urllib2.Request(gh_url) password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, gh_url, 'user', 'pass') auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) opener = urllib2.build_opener(auth_manager) urllib2.install_opener(opener) handler = urllib2.urlopen(req) print handler.getcode() print handler.headers.getheader('content-type') # ------ # 200 # 'application/json'
看,使用一个Pythonic的程序库可以简化很多工作量!那么深入学习理解类似requests的高质量程序库带给我们的收获应该完全可以预期:一定是非常大的!
最后,除了修炼内功外,也可以尝试利用工具达到事半功倍的效果。所以接下来介绍风格检查程序PEP8。其实一开始PEP8是一篇关于Python编码风格的指南,它提出了保持代码一致性的细节要求。它至少包括了对代码布局、注释、命名规范等方面的要求,在代码中遵循这些原则,有利于编写Pythonic的代码。比如,对代码的换行,不好的风格如下:
if foo == 'blah': do_blah_thing() do_one(); do_two(); do_three()
而Pythonic的风格则是这样的:
if foo == 'blah': do_blah_thing() do_one() do_two() do_three()
如果要“人肉”检查代码是否符合PEP8规范,则比较困难,而且容易跟同僚引发争论。所以Johann C. Rocholl开发了一个应用程序来进行检测,就是应用程序PEP8。当然,它是使用Python开发的,安装它非常容易。
$ pip install -U pep8
在自己的shell中执行这一命令就可以安装成功了(首先需要安装pip)。然后即可简单地用它检测一下自己的代码。
$ pep8 --first optparse.py optparse.py:69:11: E401 multiple imports on one line optparse.py:77:1: E302 expected 2 blank lines, found 1 optparse.py:88:5: E301 expected 1 blank line, found 0 optparse.py:222:34: W602 deprecated form of raising exception optparse.py:347:31: E211 whitespace before '(' optparse.py:357:17: E201 whitespace after '{' optparse.py:472:29: E221 multiple spaces before operator optparse.py:544:21: W601 .has_key() is deprecated, use 'in'
可以看到上面有许多错误和警告,然后我们按图索骥逐一修复它们就可以了。如果嫌这种报表不够细致,可以考虑使用--show-source参数让PEP8显示每一个错误和警告对应的代码。
$ pep8 --show-source --show-pep8 testsuite/E40.py testsuite/E40.py:2:10: E401 multiple imports on one line import os, sys ^ Imports should usually be on separate lines. Okay: import os\nimport sys E401: import sys, os
看,它甚至可以给出“正确”的写法!除了针对某一个源代码文件以外,它还可以直接检测一个项目的质量,并通过直观的报表给出报告。
$ pep8 --statistics -qq Python-2.5/Lib 232 E201 whitespace after '[' 599 E202 whitespace before ')' 631 E203 whitespace before ',' 842 E211 whitespace before '(' 2531 E221 multiple spaces before operator 4473 E301 expected 1 blank line, found 0 4006 E302 expected 2 blank lines, found 1 165 E303 too many blank lines (4) 325 E401 multiple imports on one line 3615 E501 line too long (82 characters) 612 W601 .has_key() is deprecated, use 'in' 1188 W602 deprecated form of raising exception
PEP8有优秀的插件架构,可以方便地实现特定风格的检测(例如,有些公司、团队会定义自己的风格);它生成的报告易于处理,可以很方便地与编辑器集成(例如,实现点击出错信息跳转到相应代码行)。所以这是一个非常有用的工具,它可以提升你对Pythonic的认识,达到编写高质量代码的目的。
PEP8不是唯一的编程规范,事实上,有些公司制定的编程规范也非常有参考意义,比如Google Python Style Guide。同样,PEP8也不是唯一的风格检测程序,类似的应用还有Pychecker、Pylint、Pyflakes等。其中,Pychecker是Google Python Style Guide推荐的工具;Pylint因可以非常方便地通过编辑配置文件实现公司或团队的风格检测而受到许多人的青睐;Pyflakes则因为易于集成到vim中,所以使用的人也非常多。
其实Pythonic的代码,往往是放弃自我风格的代码,而要有“放弃自我风格”的觉悟,是非常困难、非常痛苦的。要突破这种瓶颈,完成自我蜕变,除了需要付出许多精力去学习外,参考更好的书籍进行辅助也是相当有帮助的。目前市面上针对编写“高质量”的Python程序的方法的书籍并不多,本书应是一本比较好的参考资料。作为作者,我们也真心希望自己的一点点经验分享能够对读者有所帮助。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论