本文是The Best of the Best Practices (BOBP) Guide for
Python的中文翻译,并加入了一些我的说明和理解。
总体原则
价值观
「为别人开发你也想要使用的工具。」 - Kenneth Reitz (requests等知名库作者)
你自己都不想用的东西做出来有什么意义呢?
「简洁总是胜过可用。」 - Pieter Hintjens (ZeroMQ)
我对函数式编程的看法一直是「看场景」, 甚至于我经常会对比性能, 义无反顾的使用性能更好、代码简洁的那种。
「满足90%的使用场景。忽略那些说不的人。」 - Kenneth Reitz
程序员都有完美主义情怀, 但是其实往往我们是在偏激的看事情,做自认为很酷很有用的功能,而用户其实并不买账。
「优美胜过丑陋。」 - PEP 20
「为开源(甚至是闭源项目)而开发。」
一般开发准则
「明确胜过含蓄。」- PEP 20
不要留坑, 我经常看到一些复杂的代码, 这些代码的作者写的时候明显知道自己在做什么, 但是别人很难维护和看懂.
所以我对自己的职业的基本要求就是: 那天我离职了, 后来接手的人不会经常骂我
「可读性应当被重视」- PEP 20
「任何人都可以解决任何问题」- 可汗学院开发文档
「一旦发现破窗(设计错误,决策失误或编码质量低),马上修补。
我们改bug有个原则 - 测试要覆盖到出bug的地方。有问题及时解决
「现在做也要胜过不去做。」- PEP 20
明日复明日, 明日何其多. 我们在代码review的时候, 问题需要在提出的时候就去改, 永远不会说下一次再说, 因为下一次大多时候是没有下一次了
「测试要彻底。撰写新功能文档。」
「相对于人力驱动型开发,测试驱动型开发更重要。」
「这些准则可能,应该是很可能在未来会改变。」
特殊准则
风格
感觉合理的话,就遵循PEP 8。
命名
- 变量、函数、方法、包、模块小写,并使用下划线分隔单词(lower_case_with_underscores)
- 类、异常首字母大写(CapWords)
- 受保护的方法和内部函数单下划线开头(_single_leading_underscore(self, …))
- 私有的方法双下划线开头(__double_leading_underscore(self, …))
- 常量字母全部大写,单词间用下划线分隔(ALL_CAPS_WITH_UNDERSCORES)
一般命名准则
尽量不要使用只有一个字母的变量名(例如,l,I,O等)。
例外:在很简短的代码块中,如果变量名的意思可以从上下文明显地看出来。比如下面的例子:
1 |
|
避免重复变量名,正确的做法:
1 |
|
错误的做法:
1 |
|
「反向标记」更好,正确的做法:
1 |
|
错误的做法:
1 |
|
避免使用getter和setter方法,正确的做法
1 |
|
错误的做法:
1 |
|
缩进
用4个空格符——永远别用Tab制表符。
模块引用
引用整个模块,而不是模块中的单个标识符。举个例子,假设一个cantee模块下面,有一个canteen/sessions.py文件,
正确的做法:
1 |
|
错误的做法:
1 |
|
例外:如果第三方代码的文档中明确说明要单个引用。
理由:避免循环引用。[看这里](https://sites.google.com/a/khanacademy.org/forge/for-
developers/styleguide/python#TOC-Imports)。
把代码引用部分放在文件的顶部,按下面的顺序分成三个部分,每个部分之间空一行。
- 系统引用
- 第三方引用
- 本地引用
理由:明确显示每个模块的引用来源。文档
遵循PEP
257提出的文档字符串准则。reStructuredText
(reST) 和Sphinx有助于确保文档符合标准。
对于功能明显的函数,撰写一行文档字符串:
1 |
|
多行文档字符串应包括:
- 一行摘要
*合适的话,请描述使用场景 - 参数
- 返回数据类型和语义信息,除非返回None
1 |
|
注意:
- 使用主动词(Return),而不是描述性的单词(Returns)。
- 在类的文档字符串中为init方法撰写文档。
1 |
|
关于注释
尽量少用。与其写很多注释,不如提高代码可读性。通常情况下,短小的方法比注释更有效。
错误的做法:
1 |
|
正确的做法:
1 |
|
但是的确要写注释时,请牢记:「遵循斯托克与怀特所写的《风格的要素》。」 —— PEP 8
每行的长度
不要过分在意。80到100个字符都是没问题的。
使用括号延续当前行。
1 |
|
测试
尽量争取测试全部代码,但也不必执着于覆盖率。
一般测试准则
- 使用较长的、描述性的名称。通常情况下,这能避免在测试方法中再写文档。
- 测试之间应该是孤立的。不要与真实地数据库或网络进行交互。使用单独的测试数据库,测试完即可销毁,或者是使用模拟对象。
- 使用工厂模式,而不是fixture。
- 别让不完整的测试通过,否则你就有可能忘记。你应该加上一些占位语句,比如
assert False, "TODO: finish me"
。单元测试
- 每次聚焦一个很小的功能点。
- 运行速度要快,但是速度慢总比不测试好。
- 通常,每一个类或模型都应该有一个测试用例类。
1 |
|
功能测试
功能测试是更高层次的测试,更接近最终用户如何与应用交互这一层面。通常用在网络应用与图形应用测试。
- 按照场景撰写测试。测试用例的测试方法命名应该看上去像场景描述。
- 在编写代码之前,通过注释说明具体场景信息。
1 |
|
请注意,测试用例的类名称和测试方法的名称放在一起,就像是「测试一名用户能否发布博文」。
引用
- PEP 20 (The Zen of Python)
- PEP 8 (Style Guide for Python)
- The Hitchiker’s Guide to Python
- Khan Academy Development Docs
- Python Best Practice Patterns
- Pythonic Sensibilities
- The Pragmatic Programmer
- 以及其他诸多资料
版权声明:本文由 董伟明 原创,未经作者授权禁止任何微信公众号和向掘金(juejin.im)转载,技术博客转载采用 保留署名-非商业性使用-禁止演绎 4.0-国际许可协议
python