Python的禅(1)
这些是python的指导原则,但是诠释是开放的。对这些原则合适的解释是需要一些幽默感的。如果你正在使用以小品喜剧艺术团的名字命名的一种编程语言,你最好具有幽默感。Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
...
Python的禅(2)
In the face of ambiguity, refuse the temptation to guess.
There should be one—and preferably only one—obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than right now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea—let's do more of those!
这首特别的“诗”开始作为一个笑话,但它确实包含了很多关于Python背后的哲学真理。 Python的禅已经正式成文PEP 20,它的摘要是:Python老手Tim Peters 把BDFL(http://en.wikipedia.org/wiki/BDFL)的python代码设计的指导原则简洁地总结成20条格言,只有19条被记录下来。 如果你是一个“Pythoneer”或“Pythonista”,你可以自己决定,python的禅有不同的内涵。 如果存在疑问: Import this 尝试在Python交互式解释: >>> import this Python中还有一个复活节彩蛋: >>> from __future__ import braces File "<stdin>", line 1 SyntaxError: not a chance 一群喜剧演员!
编程风格:读胜于写
程序必须是写来给人读得,只是顺带让机器执行。
—Abelson & Sussman, 计算机程序的构造和解释
尽量让你的程序易于阅读和明显。
值得阅读:http://www.python.org/dev/peps/pep-0008/
PEP=Python的增强建议
一个PEP是向python社区提供信息的设计文档,或描述Python或过程或环境的新功能。
Python社区有着自己的代码风格的标准,这些标准编纂在PEP 8中。这些标准是与其他社区的不同,如C,C +,C#,Java,VisualBasic等等。
因为缩进和空格在python中至关重要,Python代码风格指南几乎就是标准。遵循风格指南是将是十分明智。大多数开源项目和内部项目紧紧地遵循风格指南。
空格1
4个空格一个缩进层次;
最好不要使用制表符;
永远不要混用制表符和空格;( 这确实是IDLE和Emacs的Python模式的支持。 其他编辑器也可以提供这种支持。)
函数之间使用一个空行分割;
类之间使用两个空行分割
空格2
添加一个空格在字典、列表、序列、参数列表中的“,“后,以及在字典中的”:“之后,而不是之前; 在赋值和比较两边放置一个空格(参数列表中除外); 紧随括号后面或者参数列表前一个字符不要存在空格;(a, b) yes ( a, b) no Def test(a, b, c): pass yes Def test( a, b, c) no 紧随文档字符串的后面不要存在空格; “””Return a””” yes “”” Return a””” no
def make_squares(key, value=0): """Return a dictionary and a list...""" d = {key: value} l = [key, value] return d, l
命名
l 应避免的名字 永远不要用字符`l'(小写字母el(就是读音,下同)), O'(大写字母oh),或I'(大写字母eye)作为单字符的变量名. 在某些字体中,这些字符不能与数字1和0分开.当想要使用'l'时,用'L'代替它. l 模块名 模块应该是不含下划线的,简短的,小写的名字. 因为模块名被映射到文件名, 有些文件系统大小写不敏感并且截短长名字, 模块名被选为相当短是重要的---这在Unix上不是问题, 但当代码传到Mac 或Windows上就可能是个问题了. 当一个用C或C++写的扩展模块有一个伴随的Python模块,这个Python模块提供了 一个更高层(例如,更面向对象)的接口时,C/C++模块有一个前导下划线(如:_socket) Python包应该是不含下划线的,简短的,全小写的名字. l 类名 几乎没有例外,类名总是使用首字母大写单词串(CapWords)的约定. l 异常名 如果模块对所有情况定义了单个异常,它通常被叫做"error"或"Error". 似乎内建(扩展)的模块使用"error"(例如:os.error), 而Python模块通常用"Error" (例如: xdrlib.Error). 趋势似乎是倾向使用CapWords异常名. l 全局变量名 (让我们希望这些变量打算只被用于模块内部) 这些约定与那些用于函数的约定差不多.被设计可以通过"from M import *"来使用的 那些模块,应该在那些不想被导入的全局变量(还有内部函数和类)前加一个下划线). l 函数名 函数名应该为小写,可能用下划线风格单词以增加可读性. mixedCase仅被允许用于这种风格已经占优势的上下文(如: threading.py) 以便保持向后兼容. l 方法名和实例变量 这段大体上和函数相同:通常使用小写单词,必要时用下划线分隔增加可读性. 使用一个前导下划线仅用于不打算作为类的公共接口的内部方法和实例变量. Python不强制要求这样; 它取决于程序员是否遵守这个约定. 使用两个前导下划线以表示类私有的名字. Python将这些名字和类名连接在一起: 如果类Foo有一个属性名为 __a, 它不能以Foo.__a访问. (执著的用户(An insistent user)还是可以通过Foo._Foo__a得到访问权.) 通常,双前导下划线应该只用来避免与类(为可以子类化所设计)中的属性发生名字冲突.
长行&续行
保持一行的字数在80个以下;
使用缩进的续行在圆括号、方括号、花括号
def __init__(self, first, second, third, fourth, fifth, sixth): output = (first + second + third + fourth + fifth + sixth)
最后选择续行的手段是使用”\”(最不推荐的方式)
VeryLong.left_hand_side \ = even_longer.right_hand_side()
反斜杠是脆弱的,它们必须是行尾(也就是一行的最后一个字符),如果在反斜杠后面添加一个空格的话,它们将不再起作用。同样,反斜杠也是丑陋的。
文档化和注释
注释块
注释块通常应用于跟随着一些(或者全部)代码并和这些代码有着相同的缩进层次. 注释块中每行以'#'和一个空格开始(除非他是注释内的缩进文本). 注释块内的段落以仅含单个'#'的行分割. 注释块上下方最好有一空行包围(或上方两行下方一行,对一个新函数定义段的注释).
行内注释
一个行内注释是和语句在同一行的注释.行内注释应该谨慎适用. 行内注释应该至少用两个空格和语句分开. 它们应该以'#'和单个空格开始.
x = x+1 # Increment x
如果语意是很明了的,那么行内注释是不必要的,事实上是应该被去掉的. 不要这样写:
x = x+1 # Increment x x = x+1 # Compensate for border
但是有时,这样是有益的:
x = x+1 # Compensate for border
文档化
为所有公共模块,函数,类和方法编写文档字符串.文档字符串对非公开的方法不是必要的,但你应该有一个描述这个方法做什么的注释.这个注释应该在"def"这行后.
PEP 257 描述了好的文档字符串的约定.一定注意,多行文档字符串结尾的""" 应该单独成行,例如:
"""Return a foobang Optional plotz says to frobnicate the bizbaz first. """
对单行的文档字符串,结尾的"""在同一行也可以.
实用性优于一致性
愚蠢得使用一致性是无知的妖怪(A Foolish Consistency is the Hobgoblin of Little Minds)
打破一条既定规则的两个好理由:
l 当应用这个规则是将导致代码可读性下降,即便对某人来说,他已经习惯于按这条规则来阅读代码了.
l 为了和周围的代码保持一致而打破规则(也许是历史原因)
-- 虽然这也是个清除其它混乱的好机会(真正的XP风格).
交互式中“_”
这的确是一个有用的功能,然而知道的人不多。
在交互式解释器,每当你计算一个表达式或调用一个函数,其结果必然绑定到一个临时名称,_(下划线):
>>> 1 + 1 2 >>> _ 2
_(下划线)存储最后打印的表达。
当结果是None ,没有打印出东西,_(下划线)是不改变, 这是方便!
这仅适用于在交互式解释器,而不是在一个模块。
当你在交互式解释中解决问题以及为下一步保存临时结果的时候,_(下划线)是特别有作用的。
>>> import math >>> math.pi / 3 1.0471975511965976 >>> angle = _ >>> math.cos(angle) 0.50000000000000011 >>> _ 0.50000000000000011
从子串中生成字符串
我们想要把所有的子串串联成一个大的字符串。特别是字串的数量特别大的时候
colors = ['red', 'blue', 'green', 'yellow']
千万别这样做,这是十分低效的:
result = '' for s in colors: result += s
上面的做法具有可怕的内存使用量和糟糕的性能。 在每一个中间步骤“累加”将会计算,存储,然后被丢弃。
相反,建议这样做:
result = ''.join(colors)
字符串方法join()进行一次复制。
当你对只有几十或几百个子字符串处理,它不会太大的差别。 但是,培养有效地处理字符串的习惯,当循环数达到成千上万的时候,它会有所作为。
构建字符串--变奏曲1
这里有一些技巧来使用字符串方法join()。
如果想在字串中插入空格:
result = ' '.join(colors)
或者在字串中插入逗号:
result = ', '.join(colors)
设计建议
- 同 象None之类的单值进行比较,应该永远用:'is'或'is not'来做. 当你本意是"if x is not None"时,对写成"if x"要小心 -- 例如当你测试一个默认为None的变量或参数是否被设置为其它值时. 这个其它值可能是一个在布尔上下文中为假的值!
- 基于类的异常总是好过基于字符串的异常. 模块和包应该定义它们自己的域内特定的基异常类(base exception class), 基类应该是内建的Exception类的子类. 还始终包含一个类的文档字符串.例如:
1 class MessageError(Exception): 2 """Base class for errors in the email package."""
- 使用字符串方法(methods)代替字符串模块,除非必须向后兼容Python 2.0以前的版本. 字符串方法总是非常快,而且和unicode字符串共用同样的API(应用程序接口)
- 在检查前缀或后缀时避免对字符串进行切片. 用startswith()和endswith()代替, 因为它们是明确的并且错误更少. 例如:
No: if foo[:3] == 'bar': Yes: if foo.startswith('bar'):
- 例外是如果你的代码必须工作在Python 1.5.2 (但是我们希望它不会发生!).
- 对象类型的比较应该始终用isinstance()代替直接比较类型.例如:
No: if type(obj) is type(1): Yes: if isinstance(obj, int):
- 检查一个对象是否是字符串时,紧记它也可能是unicode字符串! 在Python 2.3, str和unicode有公共的基类,basestring,所以你可以这样做:
1 if isinstance(obj, basestring):
- 在Python 2.2 类型模块为此定义了StringTypes类型, 例如:
1 from types import StringTypes 2 if isinstance(obj, StringTypes):
- 在Python 2.0和2.1,你应该这样做:
1 from types import StringType, UnicodeType 2 if isinstance(obj, StringType) or \ 3 isinstance(obj, UnicodeType) :
- 对序列,(字符串(strings),列表(lists),元组(tuples)), 使用空列表是false这个事实,因此"if not seq"或"if seq"比 "if len(seq)"或"if not len(seq)"好.
- 书写字符串文字时不要依赖于有意义的后置空格. 这种后置空格在视觉上是不可辨别的,并且有些编辑器(特别是近来,reindent.py) 会将它们修整掉.
- 不要用 == 来比较布尔型的值以确定是True或False(布尔型是Pythn 2.3中新增的)
No: if greeting == True: Yes: if greeting: No: if greeting == True: Yes: if greeting: