geekdoc-python-zh/docs/realpython/python-pep8.md

35 KiB
Raw Blame History

如何用 PEP 8 写出漂亮的 Python 代码

原文:https://realpython.com/python-pep8/

*立即观看**本教程有真实 Python 团队创建的相关视频课程。和编写的教程一起看,加深理解: 用 PEP 8 编写漂亮的 Pythonic 代码

PEP8有时拼写为 PEP 8 或 PEP-8是一个提供如何编写 Python 代码的指南和最佳实践的文档。它是由吉多·范·罗苏姆、巴里·华沙和尼克·科格兰在 2001 年写的。PEP 8 的主要目的是提高 Python 代码的可读性和一致性。

PEP 代表 Python 增强提议有好几个。PEP 是一个文档,它描述了为 Python 提出的新特性,并为社区记录了 Python 的一些方面,如设计和风格。

本教程概述了 PEP 8 中的主要指导方针。它的目标是初级到中级程序员,因此我没有涉及一些最高级的主题。你可以通过阅读完整的 PEP 8 文档来了解这些。

本教程结束时,你将能够:

  • 写符合 PEP 8 的 Python 代码
  • 理解人教版 8 中的指导原则背后的原因
  • 设置您的开发环境,以便您可以开始编写符合 PEP 8 的 Python 代码

免费奖励: 掌握 Python 的 5 个想法,这是一个面向 Python 开发者的免费课程,向您展示将 Python 技能提升到下一个水平所需的路线图和心态。

为什么我们需要 PEP 8

"可读性很重要。"

Python 之禅

PEP 8 的存在是为了提高 Python 代码的可读性。但是为什么可读性如此重要呢?为什么编写可读代码是 Python 语言的指导原则之一?

正如吉多·范·罗苏姆所说,“代码被阅读的次数比它被编写的次数多得多。”您可能要花几分钟,或者一整天,编写一段代码来处理用户认证。一旦你写了,你就不会再写了。但是你一定要再读一遍。这段代码可能仍然是您正在进行的项目的一部分。每次你回到那个文件,你都必须记住代码做了什么,为什么要写它,所以可读性很重要。

如果你是 Python 的新手,在你写完一段代码后的几天或几周内,很难记住这段代码做了什么。如果你遵循 PEP 8你可以确定你已经很好地命名了你的变量。您将知道您已经添加了足够多的空白,因此在代码中遵循逻辑步骤更加容易。你也会很好地注释你的代码。所有这些都将意味着你的代码可读性更强,更容易理解。作为初学者,遵循 PEP 8 的规则可以使学习 Python 成为一项更加愉快的任务。

如果你在找一份开发工作,遵循 PEP 8 尤其重要。编写清晰易读的代码显示了专业性。这会告诉雇主你知道如何很好地组织你的代码。

如果你有更多编写 Python 代码的经验,那么你可能需要与其他人合作。在这里编写可读的代码是至关重要的。其他人,可能从未见过你或见过你的编码风格,将不得不阅读和理解你的代码。拥有你所遵循和认可的指导方针将会让其他人更容易阅读你的代码。

Remove ads

命名惯例

“显性比隐性好。”

Python 之禅

当你写 Python 代码时,你必须命名很多东西:变量、函数、类、包等等。选择明智的名字会节省你以后的时间和精力。你将能够从名字中猜出某个变量、函数或类代表什么。您还将避免使用不合适的名称,这可能会导致难以调试的错误。

注意:切勿使用lOI单字母名称,因为根据字体不同,这些名称可能会被误认为10:

O = 2  # This may look like you're trying to reassign 2 to zero

命名风格

下表概述了 Python 代码中的一些常见命名样式以及何时应该使用它们:

类型 命名约定 例子
功能 使用小写单词。用下划线分隔单词以提高可读性。 functionmy_function
可变的 使用小写的单个字母、单词或多个单词。用下划线分隔单词以提高可读性。 xvarmy_variable
班级 每个单词以大写字母开头。不要用下划线分隔单词。这种风格被称为骆驼案或者帕斯卡案 ModelMyClass
方法 使用小写单词。用下划线分隔单词以提高可读性。 class_methodmethod
常数 使用大写的单个字母、单词或多个单词。用下划线分隔单词以提高可读性。 CONSTANTMY_CONSTANTMY_LONG_CONSTANT
组件 使用一个或多个短的小写单词。用下划线分隔单词以提高可读性。 module.pymy_module.py
包裹 使用一个或多个短的小写单词。不要用下划线分隔单词。 packagemypackage

这些是一些常见的命名约定以及如何使用它们的示例。但是,为了编写可读的代码,您仍然必须小心选择字母和单词。除了在代码中选择正确的命名风格,您还必须仔细选择名称。以下是如何尽可能有效地做到这一点的几点建议。

如何选择名字

为变量、函数、类等等选择名称可能很有挑战性。在编写代码时,您应该在命名选择上多加考虑,因为这将使您的代码更具可读性。在 Python 中命名对象的最佳方式是使用描述性名称,以便清楚地表明对象代表什么。

在命名变量时,您可能会倾向于选择简单的单字母小写名称,如x。但是,除非你使用x作为数学函数的自变量,否则不清楚x代表什么。假设您将一个人的名字存储为一个字符串,并且您想使用字符串切片对他们的名字进行不同的格式化。您可能会得到这样的结果:

>>> # Not recommended
>>> x = 'John Smith'
>>> y, z = x.split()
>>> print(z, y, sep=', ')
'Smith, John'

这是可行的,但是你必须记住xyz代表什么。也可能让合作者感到困惑。更清晰的名称选择应该是这样的:

>>> # Recommended
>>> name = 'John Smith'
>>> first_name, last_name = name.split()
>>> print(last_name, first_name, sep=', ')
'Smith, John'

同样,为了减少打字量,在选择名字时使用缩写会很有诱惑力。在下面的例子中,我定义了一个函数db(),它接受一个参数x,并将其加倍:

# Not recommended
def db(x):
    return x * 2

乍一看,这似乎是一个明智的选择。很容易成为 double 的缩写。但是想象一下几天后回到这段代码。你可能已经忘记了你想用这个函数实现什么,这使得猜测你如何缩写它变得很困难。

下面的例子就清楚多了。如果您在编写这段代码几天后再来看这段代码,您仍然能够阅读并理解这个函数的用途:

# Recommended
def multiply_by_two(x):
    return x * 2

同样的理念也适用于 Python 中的所有其他数据类型和对象。尽可能使用最简洁但具有描述性的名称。

Remove ads

代码布局

“漂亮总比难看好。”

Python 之禅

你如何布局你的代码对它的可读性有很大的影响。在这一节中,您将学习如何添加垂直空格来提高代码的可读性。您还将学习如何处理 PEP 8 中推荐的 79 个字符的行限制。

空白行

垂直空白,或空白行,可以大大提高代码的可读性。堆积在一起的代码可能会让人不知所措,难以阅读。类似地,代码中太多的空行会使代码看起来非常稀疏,读者可能需要进行不必要的滚动。下面是关于如何使用垂直空格的三个关键指导原则。

用两个空行包围顶级函数和类。顶级函数和类应该是完全独立的,并处理独立的功能。在它们周围留出额外的垂直空间是有意义的,这样就能清楚地看出它们是分开的:

class MyFirstClass:
    pass

class MySecondClass:
    pass

def top_level_function():
    return None

用一个空行包围类中的方法定义。在一个类中,所有的函数都是相互关联的。最好在它们之间只留一行:

class MyClass:
    def first_method(self):
        return None

    def second_method(self):
        return None

**函数内部尽量少用空行,以显示清晰的步骤。**有时候,一个复杂的函数要在 return语句之前完成几个步骤。为了帮助读者理解函数内部的逻辑,在每个步骤之间留一个空行会很有帮助。

在下面的例子中,有一个函数计算一个列表的方差。这是一个分两步的问题,所以我在每一步之间留了一个空行。在return语句前还有一个空行。这有助于读者清楚地看到返回的内容:

def calculate_variance(number_list):
    sum_list = 0
    for number in number_list:
        sum_list = sum_list + number
    mean = sum_list / len(number_list)

    sum_squares = 0
    for number in number_list:
        sum_squares = sum_squares + number**2
    mean_squares = sum_squares / len(number_list)

    return mean_squares - mean**2

如果你小心使用垂直空格,它可以大大提高你的代码的可读性。它有助于读者直观地理解您的代码是如何分成几个部分的,以及这些部分是如何相互关联的。

最大线路长度和断线

PEP 8 建议行数应限制在 79 个字符以内。这是因为它允许您一个接一个地打开多个文件,同时避免换行。

当然,将语句控制在 79 个字符以内并不总是可能的。PEP 8 概述了允许语句跨几行运行的方法。

如果代码包含在圆括号、中括号或大括号中Python 将假定行连续:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

如果不能使用隐式延续,那么可以使用反斜杠来换行:

from mypkg import example1, \
    example2, example3

但是,如果您可以使用隐式延续,那么您应该这样做。

如果需要在二元操作符周围换行,比如+*,它应该在操作符之前换行。这条规则源于数学。数学家们一致认为,在二进制运算符之前中断可以提高可读性。比较下面两个例子。

以下是在二元运算符前中断的示例:

# Recommended
total = (first_variable
         + second_variable
         - third_variable)

您可以立即看到哪个变量被增加或减少,因为运算符就在被运算的变量旁边。

现在,让我们来看一个二元运算符后的中断示例:

# Not Recommended
total = (first_variable +
         second_variable -
         third_variable)

在这里,很难看出哪个变量在增加,哪个变量在减少。

在二进制操作符之前中断会产生更可读的代码,所以 PEP 8 鼓励这样做。二元运算符后持续中断的代码仍然符合 PEP 8。但是我们鼓励您在二元运算符前中断。

Remove ads

缩进

"应该有一种——最好只有一种——显而易见的方法来做这件事。"

Python 之禅

缩进或前导空格在 Python 中非常重要。Python 中代码行的缩进级别决定了语句如何分组。

考虑下面的例子:

x = 3
if x > 5:
    print('x is larger than 5')

缩进的 print语句让 Python 知道只有当if语句返回True时才应该执行。同样的缩进也适用于告诉 Python 在调用函数时执行什么代码,或者什么代码属于给定的类。

PEP 8 规定的关键缩进规则如下:

  • 使用 4 个连续空格表示缩进。
  • 比制表符更喜欢空格。

制表符与空格

如上所述,缩进代码时应该使用空格而不是制表符。当您按下 Tab 键时,您可以调整文本编辑器中的设置以输出 4 个空格而不是一个制表符。

如果您正在使用 Python 2并且已经混合使用了制表符和空格来缩进代码那么在尝试运行它时您不会看到错误。为了帮助您检查一致性您可以在从命令行运行 Python 2 代码时添加一个-t标志。当您使用制表符和空格不一致时,解释器将发出警告:

$ python2 -t code.py
code.py: inconsistent use of tabs and spaces in indentation

相反,如果您使用-tt标志,解释器将发出错误而不是警告,您的代码将不会运行。使用这种方法的好处是解释器告诉你不一致的地方在哪里:

$ python2 -tt code.py
 File "code.py", line 3
 print(i, j)
 ^
TabError: inconsistent use of tabs and spaces in indentation

Python 3 不允许混合使用制表符和空格。因此,如果您使用的是 Python 3则会自动发出这些错误:

$ python3 code.py
 File "code.py", line 3
 print(i, j)
 ^
TabError: inconsistent use of tabs and spaces in indentation

您可以使用制表符或空格来表示缩进,从而编写 Python 代码。但是,如果您正在使用 Python 3您必须与您的选择保持一致。否则您的代码将不会运行。PEP 8 建议您始终使用 4 个连续空格来表示缩进。

换行后的缩进

当您使用行继续符将行保持在 79 个字符以下时,使用缩进来提高可读性是很有用的。它允许读者区分两行代码和跨越两行的一行代码。您可以使用两种缩进样式。

第一个是将缩进的块与开始分隔符对齐:

def function(arg_one, arg_two,
             arg_three, arg_four):
    return arg_one

有时,您会发现只需要 4 个空格来对齐开始分隔符。这通常出现在跨越多行的if语句中,因为if、空格和左括号组成了 4 个字符。在这种情况下,很难确定if语句中的嵌套代码块从哪里开始:

x = 5
if (x > 3 and
    x < 10):
    print(x)

在这种情况下PEP 8 提供了两种替代方法来帮助提高可读性:

  • 在最终条件后添加注释。由于大多数编辑器中的语法突出显示,这将把条件从嵌套代码中分离出来:

    x = 5
    if (x > 3 and
        x < 10):
        # Both conditions satisfied
        print(x)` 
    
  • 在行延续上添加额外的缩进:

    x = 5
    if (x > 3 and
            x < 10):
        print(x)` 
    

换行符后的另一种缩进样式是悬挂缩进。这是一个印刷术语,意思是段落或语句中除第一行以外的每一行都缩进。您可以使用悬挂缩进来直观地表示一行代码的延续。这里有一个例子:

var = function(
    arg_one, arg_two,
    arg_three, arg_four)

注意:当你使用悬挂缩进时,第一行不能有任何参数。以下示例不符合 PEP 8:

# Not Recommended
var = function(arg_one, arg_two,
    arg_three, arg_four)

当使用悬挂缩进时,添加额外的缩进来区分连续行和函数中包含的代码。下面的示例很难阅读,因为函数内部的代码与后续行的缩进级别相同:

# Not Recommended
def function(
    arg_one, arg_two,
    arg_three, arg_four):
    return arg_one

相反,最好在行继续符上使用双缩进。这有助于区分函数参数和函数体,从而提高可读性:

def function(
        arg_one, arg_two,
        arg_three, arg_four):
    return arg_one

当您编写符合 PEP 8 的代码时79 个字符的行限制迫使您在代码中添加换行符。为了提高可读性,您应该缩进一个续行,以表明它是一个续行。有两种方法可以做到这一点。第一个是将缩进的块与开始分隔符对齐。第二种是使用悬挂式缩进。您可以自由选择在换行后使用哪种缩进方法。

Remove ads

右大括号放在哪里

换行允许您在圆括号、方括号或大括号内换行。很容易忘记右大括号但是把它放在一个合理的地方是很重要的。否则会使读者感到困惑。PEP 8 为隐含行延续中的右大括号位置提供了两个选项:

  • 将右大括号与前一行的第一个非空白字符对齐:

    list_of_numbers = [
        1, 2, 3,
        4, 5, 6,
        7, 8, 9
        ]` 
    
  • 将右大括号与开始构造的行的第一个字符对齐:

    list_of_numbers = [
        1, 2, 3,
        4, 5, 6,
        7, 8, 9
    ]` 
    

你可以自由选择使用哪个选项。但是,一如既往,一致性是关键,所以尝试坚持以上方法之一。

评论

"如果实现很难解释,这是一个坏主意."

Python 之禅

您应该在编写代码时使用注释来记录代码。重要的是将你的代码文档化,这样你和任何合作者都能理解它。当您或其他人阅读注释时,他们应该能够容易地理解该注释所适用的代码,以及它如何与您的代码的其余部分相适应。

向代码中添加注释时,需要记住以下要点:

  • 将注释和文档字符串的行长度限制为 72 个字符。
  • 使用完整的句子,以大写字母开头。
  • 如果您更改代码,请确保更新注释。

块注释

使用块注释来记录一小部分代码。当您必须编写几行代码来执行单个操作(例如从文件导入数据或更新数据库条目)时,它们非常有用。它们很重要,因为它们帮助其他人理解给定代码块的用途和功能。

PEP 8 为编写块注释提供了以下规则:

  • 将块注释缩进到与它们描述的代码相同的级别。
  • 每行以一个#开头,后跟一个空格。
  • 用包含单个#的行分隔段落。

以下是解释for循环功能的块注释。请注意,该句子会换行以保留 79 个字符的行限制:

for i in range(0, 10):
    # Loop over i ten times and print out the value of i, followed by a
    # new line character
    print(i, '\n')

有时,如果代码非常专业,那么有必要在块注释中使用多个段落:

def quadratic(a, b, c, x):
    # Calculate the solution to a quadratic equation using the quadratic
    # formula.
    #
    # There are always two solutions to a quadratic equation, x_1 and x_2.
    x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
    x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    return x_1, x_2

如果你对什么类型的注释合适有疑问,那么块注释通常是个不错的选择。在你的代码中尽可能多地使用它们,但是如果你对你的代码做了修改,一定要更新它们!

行内注释

行内注释解释一段代码中的一条语句。它们有助于提醒您,或者向他人解释,为什么某一行代码是必需的。以下是 PEP 8 对他们的评价:

  • 谨慎使用行内注释。
  • 将行内注释写在它们所引用的语句所在的同一行。
  • 用两个或更多空格将行内注释与语句分隔开。
  • 像块注释一样,用一个#和一个空格开始行内注释。
  • 不要用它们来解释显而易见的事情。

下面是一个行内注释的示例:

x = 5  # This is an inline comment

有时,行内注释似乎是必要的,但是您可以使用更好的命名约定来代替。这里有一个例子:

x = 'John Smith'  # Student Name

这里,行内注释给出了额外的信息。然而,使用x作为人名的变量名是不好的做法。如果重命名变量,则不需要行内注释:

student_name = 'John Smith'

最后,像这样的行内注释是不好的做法,因为它们陈述了明显而混乱的代码:

empty_list = []  # Initialize empty list

x = 5
x = x * 5  # Multiply x by 5

内联注释比块注释更具体,在不必要的时候很容易添加它们,这会导致混乱。你可以只使用块注释,所以,除非你确定你需要行内注释,如果你坚持块注释,你的代码更有可能是 PEP 8 兼容的。

Remove ads

文档字符串

文档字符串,或称文档字符串,是用双引号(""")或单引号(''')括起来的字符串,出现在任何函数、类、方法或模块的第一行。您可以使用它们来解释和记录特定的代码块。有一个完整的 PEP PEP 257 ,涵盖了 docstrings但是您将在这一节中得到一个摘要。

适用于文档字符串的最重要的规则如下:

  • 用三个双引号将文档字符串括起来,如"""This is a docstring"""所示。

  • 为所有公共模块、函数、类和方法编写它们。

  • 将结束多行文档字符串的"""单独放在一行中:

    def quadratic(a, b, c, x):
        """Solve quadratic equation via the quadratic formula.
    
     A quadratic equation has the following form:
     ax**2 + bx + c = 0
    
     There always two solutions to a quadratic equation: x_1 & x_2.
     """
        x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
        x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    
        return x_1, x_2` 
    
  • 对于单行文档字符串,保持"""在同一行:

    def quadratic(a, b, c, x):
        """Use the quadratic formula"""
        x_1 = (- b+(b**2-4*a*c)**(1/2)) / (2*a)
        x_2 = (- b-(b**2-4*a*c)**(1/2)) / (2*a)
    
        return x_1, x_2` 
    

关于记录 Python 代码的更详细的文章,请参见 James Mertz 的记录 Python 代码:完整指南

表达式和语句中的空格

“疏比密好。”

Python 之禅

如果使用得当,空格在表达式和语句中非常有用。如果没有足够的空白,那么代码可能很难阅读,因为它们都被捆绑在一起。如果有太多的空白,那么就很难在一个语句中直观地组合相关的术语。

二元运算符周围的空格

用一个空格将下列二元运算符括起来:

  • 赋值运算符(=+=-=等等)

  • 比较(==!=><)。>=<=)和(isis notinnot in)

  • 布尔型(andnotor)

注意:当=用于给函数参数赋值默认值时,不要用空格将其括起来。

# Recommended
def function(default_parameter=5):
    # ...

# Not recommended
def function(default_parameter = 5):
    # ...

当一个语句中有多个操作符时,在每个操作符前后添加一个空格看起来会令人困惑。相反,最好只在优先级最低的操作符周围添加空格,尤其是在执行数学运算时。这里有几个例子:

# Recommended
y = x**2 + 5
z = (x+y) * (x-y)

# Not Recommended
y = x ** 2 + 5
z = (x + y) * (x - y)

您也可以将此应用于有多个条件的if语句:

# Not recommended
if x > 5 and x % 2 == 0:
    print('x is larger than 5 and divisible by 2!')

在上面的例子中,and操作符的优先级最低。因此,将if语句表达如下可能更清楚:

# Recommended
if x>5 and x%2==0:
    print('x is larger than 5 and divisible by 2!')

您可以自由选择哪个更清晰,但要注意的是,您必须在操作符的两边使用相同数量的空白。

以下情况是不可接受的:

# Definitely do not do this!
if x >5 and x% 2== 0:
    print('x is larger than 5 and divisible by 2!')

在切片中,冒号充当二元运算符。因此,上一节概述的规则适用,两边应该有相同数量的空白。以下列表切片示例是有效的:

list[3:4]

# Treat the colon as the operator with lowest priority
list[x+1 : x+2]

# In an extended slice, both colons must be
# surrounded by the same amount of whitespace
list[3:4:5]
list[x+1 : x+2 : x+3]

# The space is omitted if a slice parameter is omitted
list[x+1 : x+2 :]

总之,大多数操作符都应该用空格括起来。但是,这条规则有一些注意事项,比如在函数参数中,或者在一个语句中组合多个运算符时。

Remove ads

何时避免添加空格

在某些情况下添加空白会使代码更难阅读。过多的空白会使代码过于稀疏难以理解。PEP 8 非常清晰地列举了不适合使用空格的例子。

避免添加空格的最重要的地方是在行尾。这被称为尾随空白。它是不可见的,会产生难以跟踪的错误。

下面列出了一些应该避免添加空格的情况:

  • 紧接在圆括号、方括号或大括号内:

    # Recommended
    my_list = [1, 2, 3]
    
    # Not recommended
    my_list = [ 1, 2, 3, ]` 
    
  • 在逗号、分号或冒号之前:

    x = 5
    y = 6
    
    # Recommended
    print(x, y)
    
    # Not recommended
    print(x , y)` 
    
  • 在开始函数调用的参数列表的左括号之前:

    def double(x):
        return x * 2
    
    # Recommended
    double(3)
    
    # Not recommended
    double (3)` 
    
  • 在开始索引或切片的左括号之前:

    # Recommended
    list[3]
    
    # Not recommended
    list [3]` 
    
  • 在结尾逗号和右括号之间:

    # Recommended
    tuple = (1,)
    
    # Not recommended
    tuple = (1, )` 
    
  • 要对齐赋值运算符:

    # Recommended
    var1 = 5
    var2 = 6
    some_long_var = 7
    
    # Not recommended
    var1          = 5
    var2          = 6
    some_long_var = 7` 
    

确保代码中没有尾随空格。在其他情况下PEP 8 不鼓励添加额外的空白,比如在括号内,逗号和冒号前。你也不应该为了对齐操作符而添加额外的空格。

编程建议

“简单比复杂好。”

Python 之禅

您经常会发现,在 Python(以及任何其他编程语言)中,有几种方法可以执行类似的操作。在本节中,您将看到 PEP 8 提供的一些建议,以消除歧义并保持一致性。

**不要使用等价运算符将布尔值与TrueFalse进行比较。**你经常需要检查一个布尔值是真还是假。这样做时,使用如下语句会很直观:

# Not recommended
my_bool = 6 > 5
if my_bool == True:
    return '6 is bigger than 5'

这里不需要使用等价运算符==bool只能取值TrueFalse。写下以下内容就足够了:

# Recommended
if my_bool:
    return '6 is bigger than 5'

这种用布尔值执行if语句的方式需要的代码更少,也更简单,所以 PEP 8 鼓励它。

利用空序列在if语句中为假的事实。如果你想检查一个列表是否为空,你可能想检查列表的长度。如果列表为空,那么它的长度为0,当在if语句中使用时,相当于False。这里有一个例子:

# Not recommended
my_list = []
if not len(my_list):
    print('List is empty!')

然而,在 Python 中,任何空列表、字符串或元组都是 falsy 。因此,我们可以提出一个更简单的替代方案:

# Recommended
my_list = []
if not my_list:
    print('List is empty!')

虽然两个例子都会打印出List is empty!,但是第二个选项更简单,所以 PEP 8 鼓励它。

**在if语句中使用is not而不是not ... is。**如果你试图检查一个变量是否有一个定义的值,有两个选项。第一种是用x is not Noneif语句求值,如下例所示:

# Recommended
if x is not None:
    return 'x exists!'

第二种选择是对x is None进行评估,然后根据not的结果生成if声明:

# Not recommended
if not x is None:
    return 'x exists!'

虽然两个选项都会被正确评估,但第一个更简单,所以 PEP 8 鼓励它。

当你指if x is not None:的时候不要用if x:。有时,你可能有一个函数,它的参数默认为None。在检查此类参数arg是否被赋予了不同的值时,一个常见的错误是使用以下内容:

# Not Recommended
if arg:
    # Do something with arg...

这段代码检查arg是否正确。相反,您希望检查arg是否为not None,因此最好使用以下代码:

# Recommended
if arg is not None:
    # Do something with arg...

这里犯的错误是假设not None和 truthy 是等价的。你可以设置arg = []。正如我们在上面看到的,空列表在 Python 中被评估为 falsy。因此即使参数arg被赋值,条件也不满足,因此if语句体中的代码不会被执行。

**用.startswith().endswith()代替切片。**如果你试图检查一个字符串word是否以单词cat为前缀或后缀,使用列表切片似乎是明智的。然而,列表切片容易出错,您必须在前缀或后缀中硬编码字符数。对于不太熟悉 Python 列表切片的人来说,也不清楚您想要实现什么:

# Not recommended
if word[:3] == 'cat':
    print('The word starts with "cat"')

然而,这不如使用.startswith()更具可读性:

# Recommended
if word.startswith('cat'):
    print('The word starts with "cat"')

同样,当你检查后缀时,同样的原则也适用。下面的例子概述了如何检查一个字符串是否以jpg结尾:

# Not recommended
if file_name[-3:] == 'jpg':
    print('The file is a JPEG')

虽然结果是正确的,但符号有点笨拙,难以阅读。相反,您可以使用.endswith(),如下例所示:

# Recommended
if file_name.endswith('jpg'):
    print('The file is a JPEG')

与大多数这些编程建议一样,目标是可读性和简单性。在 Python 中,有许多不同的方法来执行相同的操作,因此关于选择哪种方法的指南很有帮助。

Remove ads

何时忽略 PEP 8

这个问题的简短答案是永远不会。如果你严格遵循 PEP 8你可以保证你会有干净的、专业的、可读的代码。这将有利于你以及合作者和潜在雇主。

然而PEP 8 中的一些准则在以下情况下不方便:

  • 如果遵循 PEP 8 会破坏与现有软件的兼容性
  • 如果你正在做的代码与 PEP 8 不一致
  • 如果代码需要与旧版本的 Python 保持兼容

帮助确保您的代码遵循 PEP 8 的提示和技巧

要确保你的代码符合 PEP 8需要记住很多东西。当你开发代码时记住所有这些规则可能是一项艰巨的任务。更新过去的项目以符合 PEP 8 特别耗时。幸运的是,有工具可以帮助加速这个过程。有两类工具可以用来加强 PEP 8 的兼容性:linters 和 autoformatters。

棉绒

Linters 是分析代码和标记错误的程序。他们提供了如何修复错误的建议。当作为文本编辑器的扩展安装时Linters 特别有用,因为它们会在您书写时标记错误和文体问题。在这一节中,您将看到 linters 如何工作的概述,最后是到文本编辑器扩展的链接。

Python 代码的最佳例子如下:

  • pycodestyle 是一个根据 PEP 8 中的一些样式约定来检查你的 Python 代码的工具。

    使用pip安装pycodestyle:

    $ pip install pycodestyle` 
    

    您可以使用以下命令从终端运行pycodestyle:

    $ pycodestyle code.py
    code.py:1:17: E231 missing whitespace after ','
    code.py:2:21: E231 missing whitespace after ','
    code.py:6:19: E711 comparison to None should be 'if cond is None:'` 
    
  • flake8 是一个结合了调试器pyflakespycodestyle的工具。

    使用pip安装flake8:

    $ pip install flake8` 
    

    使用以下命令从终端运行flake8:

    $ flake8 code.py
    code.py:1:17: E231 missing whitespace after ','
    code.py:2:21: E231 missing whitespace after ','
    code.py:3:17: E999 SyntaxError: invalid syntax
    code.py:6:19: E711 comparison to None should be 'if cond is None:'` 
    

    还显示了一个输出示例。

注意:输出的多余一行表示语法错误。

这些也可以作为对 AtomSublime TextVisual Studio CodeVIM 的扩展。您还可以找到关于为 Python 开发设置 Sublime TextVIM 的指南,以及在 Real Python 上对一些流行的文本编辑器的概述。

自动套用格式器

自动套用格式程序是自动重构代码以符合 PEP 8 的程序。曾经这样的程序是 black ,它自动套用符合 PEP 8 中大部分规则的代码。一个很大的不同是,它将行长度限制为 88 个字符,而不是 79 个字符。但是,您可以通过添加命令行标志来覆盖它,如下例所示。

使用pip安装black。它需要 Python 3.6+才能运行:

$ pip install black

它可以通过命令行运行,就像 linters 一样。假设您从一个名为code.py的文件中的以下不符合 PEP 8 的代码开始:

for i in range(0,3):
    for j in range(0,3):
        if (i==2):
            print(i,j)

然后,您可以通过命令行运行以下命令:

$ black code.py
reformatted code.py
All done! ✨ 🍰 ✨
```py

`code.py`会自动重新格式化成这样:

for i in range(0, 3): for j in range(0, 3): if i == 2: print(i, j)


如果你想改变行长度限制那么你可以使用`--line-length`标志:

$ black --line-length=79 code.py reformatted code.py All done! 🍰


另外两个自动套用格式器, [`autopep8`](https://pypi.org/project/autopep8/) 和 [`yapf`](https://pypi.org/project/yapf/) ,执行与`black`类似的操作。

另一个*真正的 Python* 教程Alexander van Tol 的 [Python 代码质量:工具&最佳实践](https://realpython.com/python-code-quality/),给出了如何使用这些工具的完整解释。

[*Remove ads*](/account/join/)

## 结论

现在,您知道了如何使用 PEP 8 中的指导方针编写高质量、可读的 Python 代码。虽然这些指导方针可能看起来很迂腐,但是遵循它们确实可以改进您的代码,尤其是当涉及到与潜在的雇主或合作者共享您的代码时。

在本教程中,您学习了:

*   PEP 8 是什么,为什么存在
*   为什么你应该写 PEP 8 兼容的代码
*   如何编写符合 PEP 8 的代码

除此之外,您还看到了如何使用 linters 和 autoformatters 根据 PEP 8 指南检查您的代码。

如果你想了解更多关于 PEP 8 的信息,那么你可以阅读[完整的文档](https://www.python.org/dev/peps/pep-0008/)或者访问【pep8.org】的它包含相同的信息但是格式很好。在这些文档中你会发现 PEP 8 指南的其余部分在本教程中没有涉及。

*立即观看**本教程有真实 Python 团队创建的相关视频课程。和编写的教程一起看,加深理解: [**用 PEP 8**](/courses/writing-beautiful-python-code-pep-8/) 编写漂亮的 Pythonic 代码**********