你忽略了什么PEP 8指南,你坚持哪些?

多年来,我写的Python越多,我发现自己同意大多数的指导方针,尽pipe我一直故意为了自己的原因打破一些方针。

我很想知道在PEP 8(或其他PEPs也许)人们宗教坚持和为什么,什么人发现不方便或不足。

在我的情况(一般工作),只有一些我们偏离的东西:

  • 下划线的小写字母名称,我可以看到它的点,因为它会一直保持一致,但我们倾向于使用lowerCamelCase,即使偶尔会引入一些不一致(例如部分或大写字母缩写以及后面的单词往往下到刺激的时刻)。 主要是因为我们经常使用的接近全部的API使用camelCase(一些较高,一些较低),并且由于某种原因,我发现它更易于阅读,并倾向于将下划线预留为分离令牌或规定的混乱/模糊。

  • 我仍然无法把自己的东西放在PEP规定的对象内部。 new和init我倾向于在类没有空行的时候留下正确的位置,因为我总是希望在类中读取类名和参数,这些参数在类中的作用范围相同(比如init,get和set相同的attrib或一组attribs)我只有单个空间分开,我喜欢三个类之间的空间,两个方法之间我不会精神聚合在该对象的地图。 这纯粹是为了代码的视觉效果和可读性。 我发现stream程控制内的非常紧凑的内容以及方法和对象之间的这种间隔一直引导我的眼睛正好在代码停放几个月后我想要重新阅读的地方。 它也很好地折叠我的编辑select。

  • 有些东西,而不是我坚持,这让我疯了,当我读否则书面,是制表符而不是空格(尤其是当我们使用的一些应用内编辑器没有真正的标签replacefunction,大大造成了代码库中的污染原型阶段)。

  • 事物的顺序,如import,什么import,全局等等。当这些文件被混淆或乱序的时候,这些文件会导致大量的import文件。

  • 空格中的空格,特别是当用户使用标签时,并尝试在var名称中跨越不同长度的行alignment赋值操作(并且似乎没有办法说服那些执行该操作的人看起来不错的代码不整齐) 。

  • 控制块内的间距,特别是当我在同一个stream量控制块内看到明显的随机间隔时,以及对象内用于方法的类似数量的间距。 我甚至在开始阅读这个该死的东西之前,我不得不编辑这些东西。

所以,那些是我的,也是我“违反”PEP背后的理由(有些是共同的,有些被同事所诟病的)。 我会很好奇读什么其他Pythonistas做和不做在这些方面。

“每行79个字符”部分是无稽之谈。 他们自己的例子显示了这样做时不可读的代码:

class Rectangle(Blob): def __init__(self, width, height, color='black', emphasis=None, highlight=0): if width == 0 and height == 0 and \ color == 'red' and emphasis == 'strong' or \ highlight > 100: raise ValueError("sorry, you lose") if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) Blob.__init__(self, width, height, color, emphasis, highlight) 

这就像尝试 –
阅读
新闻艺术 –
写清楚
喜欢这个。

十多年来,80列terminal已经不是一个严肃的开发环境。 当我需要从一个跛脚的80×25环境编辑时,编辑器的包装是一个小小的麻烦; 为了避免这种情况,我不会在正常的开发过程中使用我的代码。

120列的封装对于现代开发来说是非常明智的,我对140也没有问题。这个准则已经过时了,并且导致了难以阅读的代码。

PEP8说避免“在一个任务(或其他)运营商周围的多个空间与另一个空间alignment”和“从不使用多于一个空间”的math运算符,但是我并没有遵循这一点。

当相邻线条相关或非常相似时,我经常添加“无关的空白”,但不完全相同:

 search_start = (f - f_1/3) * n/fs search_stop = (f + f_1/3) * n/fs 
 b_lpf, a_lpf = filter(N, 2*pi*fc, 'low', analog=True) b_hpf, a_hpf = filter(N, 2*pi*fc, 'high', analog=True) 
 p[x > 1] = np.cosh(order * np.arccosh( x[x > 1])) p[x < -1] = (1 - 2 * (order % 2)) * np.cosh(order * np.arccosh(-x[x < -1])) 
 b0 = (1 + cos(w0))/2 b1 = -(1 + cos(w0)) 

同样,我很烦人的是,我得到的数字格式的数组格式的代码样式警告 通常是由库自身格式化的可读方式:

 a = array([[-0.198, 0.248, -1.17 , -0.629, 1.378], [-1.315, 0.947, -0.736, -1.388, 0.389], [ 0.241, -0.98 , 0.535, 0.951, 1.143], [-0.601, 1.286, -0.947, 0.037, -0.864], [ 0.178, -0.289, -1.037, -1.453, -0.369]]) 

PEP8宁愿把它这样格式化,显然,因为我们在逗号或括号之后不能有额外的空格:

 a = array([[-0.198, 0.248, -1.17, -0.629, 1.378], [-1.315, 0.947, -0.736, -1.388, 0.389], [0.241, -0.98, 0.535, 0.951, 1.143], [-0.601, 1.286, -0.947, 0.037, -0.864], [0.178, -0.289, -1.037, -1.453, -0.369]]) 

PEP8说

请注意,最重要的是,结束多行文档string的“”“应该在一行上, 最好在前面加一个空行 ,例如:

 """Return a foobang Optional plotz says to frobnicate the bizbaz first. """ 

我觉得这很奇怪,因为这只是“无关紧要的空白”,并没有明显的原因对待开盘报价与收盘报价不同。

理由是在PEP 257 :

BDFLbuild议在多行文档string的最后一段和其结束引用之间插入一个空白行,并将结束引号放在一行中。 这样,可以使用Emacs的fill-paragraph命令。

Emacs,真的吗? 每个人都应该做奇怪的事情来迎合特定编辑工具中特定命令的特质?

我也认为将文档string的开头放在引号的同一行(不是必需的,但是build议的),同时坚持认为引用是在他们自己的路线上是奇怪的。 我认为这更合乎逻辑,应该用于单行和多行文档:

 def foobang(bizbaz, plotz=None): """ Return a foobang Optional plotz says to frobnicate the bizbaz first. """ if plotz is not None: ... 

更新:大胆的部分已被删除,现在它只是说“将自己的结束报价放在一行”,并且“汇总行可能在开幕报价或在下一行的同一行”。

我不同意这个:

 - Imports should usually be on separate lines, eg: Yes: import os import sys No: import sys, os 

我总是一起写简单的import。 我没有看到将它们全部写在单独的行上的好处:它所做的就是将膨胀加到每个源文件的顶部,并将简洁和容易的types转换成边界样板文件 ,例如。 这是如此冗长的事情,它开始诱惑从其他文件复制和粘贴。

这是立即可读和可以理解的:

 import sys, os, time, gc, inspect, math, doctest 

它很短,容易脱脂,而且易于添加。 我确实使用多个import语句,如果一行中有太多的语句,当然还是需要导入。

我也一般会保持标准库的input与我自己的模块和其他库的input分开,这与PEP8推荐的分组概念是一致的。

标准是至关重要的,PEP 8是我坚持的一个非常好的风格指南。 我唯一不同意的方针是math运算符的间距。 例如PEP8坚持以下的间距

 Without PEP8 With PEP8 ---------------------------------------------------------------- y = sqrt(x**2 + y**2) y = sqrt(x ** 2 + y ** 2) a*x**3 + b*x**2 + c*x + da * x ** 3 + b * x ** 2 + c * x + d 10**(a*x + b) 10 ** (a * x + b) F = V/(sqrt(g*h) + epsilon) F = V / (sqrt(g * h) + epsilon) a*cos(nx/pi) + b*sin(nx/pi) a * cos(nx / pi) + b * sin(nx / pi) 

我试图顺从,但这是我挣扎的一个领域。 还有谁也觉得PEP8的间距会让math更难读?

更新:

PEP8被更正为推荐左侧的格式,而不鼓励右侧的格式:

是:

 i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (ab) 

没有:

 i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b) 

我公司的风格指南特别要求制表符,而不是空格。 PEP 8提示空间是可取的,但我们发现相反。 我喜欢在VIM中看到代码缩进4'空格',同事喜欢Emacs中的8'空格'。 使用选项卡可以让我们设置我们的编辑器来显示我们喜欢的代码。

请注意,在其他基于C的语言中,缩进实际上仅仅是格式化,但是在Python中, 缩进是语法 ,因此我们认为indentation level 2应该由2的东西(即制表符)表示,而不是48的东西(即空格) 。

缩进字符select可能是原始的圣火战争(甚至在VIM / Emacs火焰战争之前),所以我预计会被改写为忘记expression对这个问题的意见!

多线条件等:PEP-8明确表示要一个二元运算符之后而不是在它之前。 恐怕我看不出这种吸引力。 在条件之前,我打破了更多意义,所以在包装/续行中,每个子行都以条件开头:

 if (condition1 \ or condition2 \ or condition3): do_something() 

可以看出,我还想为子行添加一个额外的缩进,以便从下面的块中可视化地偏移它们。 PEP-8并没有对此做任何明确的说明(是吗?),但是这些例子的子句与开头括号相对应。

PEP 8说:

是:

 x = 1 y = 2 long_variable = 3 

没有:

 x = 1 y = 2 long_variable = 3 

我通常遵循它,但为了更好的可读性,我有时会使用另一个变体:

 x = 1 y = 2 long_variable = 3 

我总是使用4个空格,我尝试使用每行最多79个字符,有时不可能。 过去我也使用过像“import sys,os”这样的导入。 一般来说,我尝试坚持PEP 8。

编辑:也用:

 def foobar(): """ foobar """ 

为文档

我的“承认违规”是关于“如果”

PEP8说在一行中没有多重说明,所以如果我们必须这样做:

 if cond: actions ... 

但是当只有一个动作的时候,我更喜欢所有的动作,比如我更喜欢:

 if a == 0: b = 0 

比:

 if a == 0: b = 0 

我使用pylint, http: //pypi.python.org/pypi/pylint,它是一个很好的工具,可以让你和其他开发者访问你的代码时保持你的代码干净和可读。

虽然我没有涵盖你所说的所有话题,但是它非常有用。

你可以有这样的报告:

 carlos@debian:~/src/fcl/cltools$ pylint numbertoletters.py No config file found, using default configuration ************* Module numbertoletters C: 1: Missing docstring C: 56:es_numero: Missing docstring C: 56:es_numero: Invalid name "s" (should match [a-z_][a-z0-9_]{2,30}$) C: 56:es_numero: Invalid name "s" (should match [a-z_][a-z0-9_]{2,30}$) C: 69:convertnumbertoletters: Empty docstring C: 90:convertnumbertoletters: Operator not preceded by a space numero='%(numero)09d' % {'numero' : int(parte_entera)} ^ C: 92:convertnumbertoletters: Comma not followed by a space for i in [0,3,6]: ^^ W: 69:convertnumbertoletters: Unused argument 'languaje' C:108:unidades: Empty docstring C:108:unidades: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:108:unidades: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:112:unidades: Invalid name "u" (should match [a-z_][a-z0-9_]{2,30}$) C:118:teens: Empty docstring C:118:teens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:118:teens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:122:teens: Invalid name "t" (should match [a-z_][a-z0-9_]{2,30}$) C:127:tens: Empty docstring C:127:tens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:127:tens: Invalid name "x" (should match [a-z_][a-z0-9_]{2,30}$) C:131:tens: Invalid name "t" (should match [a-z_][a-z0-9_]{2,30}$) C:137:tercia: Empty docstring C:141:tercia: Operator not preceded by a space numero='%(numero)03d' % {'numero' : int(num)} ^ C:143:tercia: Invalid name "a" (should match [a-z_][a-z0-9_]{2,30}$) C:144:tercia: Invalid name "b" (should match [a-z_][a-z0-9_]{2,30}$) C:145:tercia: Invalid name "c" (should match [a-z_][a-z0-9_]{2,30}$) C:163:tercia: Operator not followed by a space resultado ='veinti '+unidades(c) ^ C:165:tercia: Operator not followed by a space elif b >=3 and b <= 9: ^^ C:178:tercia: Operator not followed by a space resultado ='ciento '+unidades(c) ^ C:192:tercia: Operator not followed by a space resultado ='ciento veinti '+unidades(c) ^ C:204:tercia: Operator not preceded by a space prefix='quinientos ' ^ C:206:tercia: Operator not preceded by a space prefix='setecientos ' ^ C:208:tercia: Operator not preceded by a space prefix='novecientos ' ^ C:210:tercia: Operator not preceded by a space prefix=unidades(a)+'cientos ' ^ R:137:tercia: Too many return statements (23/6) R:137:tercia: Too many branches (41/12) R:137:tercia: Too many statements (73/50) Report ====== 141 statements analysed. Raw metrics ----------- +----------+-------+------+---------+-----------+ |type |number |% |previous |difference | +==========+=======+======+=========+===========+ |code |144 |68.25 |NC |NC | +----------+-------+------+---------+-----------+ |docstring |5 |2.37 |NC |NC | +----------+-------+------+---------+-----------+ |comment |57 |27.01 |NC |NC | +----------+-------+------+---------+-----------+ |empty |5 |2.37 |NC |NC | +----------+-------+------+---------+-----------+ Statistics by type ------------------ +---------+-------+-----------+-----------+------------+---------+ |type |number |old number |difference |%documented |%badname | +=========+=======+===========+===========+============+=========+ |module |1 |NC |NC |0.00 |0.00 | +---------+-------+-----------+-----------+------------+---------+ |class |0 |NC |NC |0 |0 | +---------+-------+-----------+-----------+------------+---------+ |method |0 |NC |NC |0 |0 | +---------+-------+-----------+-----------+------------+---------+ |function |6 |NC |NC |0.00 |0.00 | +---------+-------+-----------+-----------+------------+---------+ Duplication ----------- +-------------------------+------+---------+-----------+ | |now |previous |difference | +=========================+======+=========+===========+ |nb duplicated lines |0 |NC |NC | +-------------------------+------+---------+-----------+ |percent duplicated lines |0.000 |NC |NC | +-------------------------+------+---------+-----------+ Messages by category -------------------- +-----------+-------+---------+-----------+ |type |number |previous |difference | +===========+=======+=========+===========+ |convention |32 |NC |NC | +-----------+-------+---------+-----------+ |refactor |3 |NC |NC | +-----------+-------+---------+-----------+ |warning |1 |NC |NC | +-----------+-------+---------+-----------+ |error |0 |NC |NC | +-----------+-------+---------+-----------+ Messages -------- +-----------+------------+ |message id |occurrences | +===========+============+ |C0103 |14 | +-----------+------------+ |C0322 |6 | +-----------+------------+ |C0112 |5 | +-----------+------------+ |C0323 |4 | +-----------+------------+ |C0111 |2 | +-----------+------------+ |W0613 |1 | +-----------+------------+ |R0915 |1 | +-----------+------------+ |R0912 |1 | +-----------+------------+ |R0911 |1 | +-----------+------------+ |C0324 |1 | +-----------+------------+ Global evaluation ----------------- Your code has been rated at 7.45/10 I hope it helps. 

我强烈build议使用pylint来评估你的代码,并保持一种标准的编程方式,特别是在开发者社区。 =)

我希望它有帮助。

python-mode.el, https: //launchpad.net/python-mode

同时允许定制风格:

Mx自定义variablesRET py-docstring-style RET

默认值是pep-257-nn

实施的风格有DJANGO,ONETWO,PEP-257,PEP-257-NN,SYMMETRIC和NIL。

NIL的值不会在乎引号的位置,并将docstrings视为一个正常的string,任何其他值可能会导致以下文档string样式之一:

DJANGO:

 """ Process foo, return bar. """ """ Process foo, return bar. If processing fails throw ProcessingError. """ 

一二:

 """Process foo, return bar.""" """ Process foo, return bar. If processing fails throw ProcessingError. """ 

PEP-257:

 """Process foo, return bar.""" """Process foo, return bar. If processing fails throw ProcessingError. """ 

PEP-257-NN:

 """Process foo, return bar.""" """Process foo, return bar. If processing fails throw ProcessingError. """ 

对称:

 """Process foo, return bar.""" """ Process foo, return bar. If processing fails throw ProcessingError. """ 

PEP 8的“问题”在于它在个人偏好上对大多数程序员来说是相当高度的情感。

就我个人而言,camelCase vs下划线和列alignment指令是不变的问题。 我在这里也看到很多其他答案,有时我故意破坏PEP 8,因为在这种情况下它只是“有意义的”。

在我的Python编程生涯中,有一点我简单地放弃了,开启了PEP 8.对于大多数项目来说,这是相对容易的,所以现在唯一的主要问题是列alignment。 那个人太乱了,不pipe怎么样(虽然我可恨)。 无论如何,由于我的“放弃”,我的代码现在对我的同事们更具可读性,而且令人惊讶的是:甚至对我来说(列alignment除外:p)。

我还必须认识到PEP 8为python本身做了什么:在2.x(不符合)和3.x(符合)之间,我发现“总是知道”某个特定函数的名称会更容易。 Python的“电池”现在sorting更好。

当我写小脚本时,我经常只用两个空格。

我总是使用相同的文档格式:

 def function(): """ Even if it's a single line. """