您忽略了哪些PEP 8指南,以及您坚持哪些? [关闭]

问题描述 投票:37回答:14

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

我很想知道PEP 8(或其他PEP也可能)人们虔诚地坚持和为什么,以及人们发现不方便或不足的内容。

在我的情况下(以及一般的工作),我们只有少数几个偏离的东西:

  • 下划线小写名称,我可以看到它的重点,因为它将始终保持一致,但我们倾向于使用lowerCamelCase,即使它偶尔会引入一些不一致性(例如部分或错误大写的首字母缩略词和跟随的词,这是经常下降到一时冲动的电话)。主要是因为我们经常使用的近乎全部的API使用camelCase(一些较高,一些较低),并且由于某种原因我发现它更容易阅读,并且倾向于将下划线保留为分离令牌或规定的修改/模糊。
  • 我仍然无法让自己按照PEP规定的内容来解决问题。 new和init我倾向于在类下面没有空行,因为我总是希望用类名和args读取它们,这些方法有助于类中相同的功能范围(比如init,get和set)同一个attrib或一组attribs)我只分开单个空格,我喜欢类之间的三个空格,两个方法之间我不会在该对象的地图中进行心理聚合。这再次纯粹是为了代码的视觉冲击和可读性。我发现流量控制中的内容非常紧凑,方法和物体之间的这种间距一直引起我的注意,我希望它在代码停放几个月后重新读取。它对我选择的编辑器中的折叠反应也很好。
  • 有些事情反而是我坚持,当我阅读其他文字时,这让我疯狂,是标签而不是空格(特别是当我们使用的一些应用程序内编辑器没有真正具有标签替换功能时,对代码库中的污染造成很大影响)原型设计阶段)。
  • 诸如导入之类的东西的顺序,以及什么是导入,全局变换等等。当这些文件混合或乱序时,它真的会抛弃那些具有大量导入的文件。
  • 语句中的空格,特别是当人们使用制表符并尝试在var名称中跨越不同长度的行对齐赋值操作时(并且似乎没有办法说服那些做excel看起来代码片段的人不整齐;)) 。
  • 并且在控制块内的间距,特别是当我在同一流控制块内看到明显随机的间距,然后在对象内使用类似的间距用于方法时。在我开始读这该死的东西之前,我不得不编辑那些。

所以,那些是我的,以及我“违反”PEP背后的原因(有些是共享的,有些是同事不赞同的)。我很想知道其他Pythonistas在这方面做了什么和不做什么。

python pep8 pep
14个回答
47
投票

“每行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列终端并不是一个严肃的开发环境。当我确实需要在瘫痪的80x25环境中进行编辑时,编辑器包装是一个小小的不便;为了避免这种情况,我不会在正常开发期间破坏我的代码。

120列包装对于现代开发是完全合理的,我对140没有任何问题。该指南已经过时,并且会导致难以读取的难以阅读的代码。


2
投票

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

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

if cond:
    actions
    ...

但是当只有一个动作时,我更喜欢一行,例如我更喜欢 :

if a == 0: b = 0

比:

if a == 0:
     b = 0

2
投票

PEP 8的“问题”在于它倾向于个人偏好的领域,这些领域对于大多数程序员来说具有相当大的情感。

就我个人而言,camelCase vs下划线和列对齐指令是常量问题。我在这里也看到了很多其他的反应,有时候我会故意破坏PEP 8,因为在那种特殊情况下它只是“有意义”。

我的Python编程生涯中有一点我只是放弃并转向(使用)PEP 8.对于大多数项目来说相对容易,所以现在我唯一的主要问题是列对齐。那个人太乱了,不服从(尽管我还是讨厌地做)。无论如何,由于我的“放弃”,我的代码现在对我的同事更具可读性 - 而且 - 令人惊讶的是:甚至对我来说(除了列对齐的东西:p)。

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


1
投票

我使用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.

我强烈建议使用pylint对代码进行评级,并保持标准的编程方式,特别是在开发人员社区中。 =)

我希望它有所帮助。


1
投票

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

同时允许定制风格:

M-x自定义变量RET py-docstring-style RET

默认值为pep-257-nn

实施的款式有DJANGO,ONETWO,PEP-257,PEP-257-NN,SYMMETRIC和NIL。

NIL的值不关心引号位置,并且会将docstrings视为普通字符串,任何其他值都可能导致以下docstring样式之一:

DJANGO:

"""
Process foo, return bar.
"""

"""
Process foo, return bar.

If processing fails throw ProcessingError.
"""

ONETWO:

"""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-NO:

"""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.
"""

1
投票

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

我总是对docstrings使用相同的模式:

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

39
投票

PEP8表示要避免“在赋值(或其他)操作符周围有多个空格将它与另一个操作符对齐”并且“从不使用多个空格”围绕数学运算符,但我不遵循这一点。

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

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))

同样,令人讨厌的是,我以可读的方式格式化code style warnings for arrays of numbers,它们通常由库本身格式化:

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]])

20
投票

PEP8

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

"""Return a foobang

Optional plotz says to frobnicate the bizbaz first.

"""

我觉得这很奇怪,因为它只是“无关的空白”,并且没有明显的原因,对开场报价的处理与报价不同。

理由是在PEP 257

BDFL建议在多行文档字符串中的最后一个段落与其结束引号之间插入一个空行,将结束引号放在一行上。这样,可以在其上使用Emacs的fill-paragraph命令。

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

我还认为将文档字符串的开头放在与引号相同的行(不是必需的,但建议的)上是很奇怪的,同时坚持将结束引用放在他们自己的行上。我认为这更符合逻辑,应该用于单行和多行文档字符串:

def foobang(bizbaz, plotz=None):
    """
    Return a foobang

    Optional plotz says to frobnicate the bizbaz first.
    """

    if plotz is not None:
        ...

更新:粗体部分已被删除,现在它只是说“将结束引号单独放在一行”,并且“汇总行可能与开头报价在同一行或在下一行”。


17
投票

我不同意这点:

- Imports should usually be on separate lines, e.g.:

    Yes: import os
         import sys

    No:  import sys, os

我总是一起写简单的进口。我认为将它们全部写在不同的行上并没有任何好处:它所做的就是在每个源文件的顶部添加膨胀,并将一些简洁的东西变成简单易用的东西,例如边界样板。一些非常冗长的东西,它开始很容易从其他文件中复制和粘贴。

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

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

它简短,易于浏览,易于添加。如果在一行上有太多,当然,或者如果我需要import导入,我会使用多个from语句。

我通常也会将标准库导入与我自己的模块和其他库的导入分开,这与PEP8推荐的分组概念一致。


17
投票

标准至关重要,PEP 8是我坚持的非常好的风格指南。我不同意的唯一指导是数学运算符周围的间距。 例如,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 + d              a * 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间距让数学难以阅读吗?

更新:

PEP8corrected推荐左边的格式,同时劝阻右边的格式:

是:

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

没有:

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

6
投票

我公司的风格指南专门要求标签,而不是空格。 PEP 8暗示空间是可取的,但我们发现了相反的情况。我喜欢在VIM中看到代码缩进4个“空格”,同事喜欢Emacs中的8个“空格”。使用选项卡可以让我们设置编辑器以显示我们喜欢的代码。

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

缩进字符选择可能是原始的圣火焰战争(甚至在VIM / Emacs火焰战争之前),所以我确实希望被修改为遗忘以表达对该主题的意见!


4
投票

多线条件等:PEP-8明确表示要在二元运算符之后而不是在它之前中断。我担心我无法看到它的吸引力。对于我来说,在条件之前打破更有意义,因此在包裹/续行中,每个子行以条件开头:

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

可以看出,我还想为子线添加一个额外的缩进,以便它们在视觉上偏离下面的块。 PEP-8没有明确说明这一点(是吗?),但是这些例子的子行与开头的括号排成一行。


4
投票

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

编辑:也使用:

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

用于文档


3
投票

PEP 8说:

是:

x = 1
y = 2
long_variable = 3

没有:

x             = 1
y             = 2
long_variable = 3

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

x =             1
y =             2
long_variable = 3
© www.soinside.com 2019 - 2024. All rights reserved.