PEP 8 – Python 代码风格指南中文版(二)

代码布局

制表符还是空格?

空格是首选的缩进方法。

制表符应该仅用于与已经使用制表符缩进的代码保持一致。

Python不允许在缩进中混合使用制表符和空格。

最大行长度

将所有行的最大长度限制为79个字符。

对于结构限制较少的长文本块(如文档字符串或注释),行长度应限制在72个字符以内。

限制编辑器窗口的宽度可以使得同时并排打开多个文件成为可能,并且在使用将两个版本并排显示的代码审查工具时也能很好地工作。

大多数工具默认的换行方式会破坏代码的视觉结构,使其更难以理解。这些限制是为了避免在窗口宽度设置为80个字符的编辑器中发生换行,即使工具在换行时会在最后一列放置一个标记符号。一些基于Web的工具可能根本不支持动态换行。

有些团队强烈倾向于更长的行长度。对于完全或主要由能够就此问题达成一致的团队维护的代码,将行长度限制增加到99个字符是可以的,但前提是注释和文档字符串仍然以72个字符为换行标准。

Python标准库较为保守,要求将行长度限制在79个字符以内(文档字符串/注释限制在72个字符以内)。

推荐的长行换行方式是在括号、方括号和大括号内使用Python的隐式行继续。通过将表达式放在括号中来将长行拆分成多行。这种方法应优先于使用反斜杠进行行继续。

但在某些情况下,反斜杠仍然是合适的。例如,在Python 3.10之前,对于较长的、多个with语句,由于不能使用隐式继续,因此使用反斜杠是可以接受的:

with open('/path/to/some/file/you/want/to/read') as file_1, \
     open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

(请参见之前关于多行if语句的讨论,以获取关于此类多行with语句缩进的更多想法。)

另一个这样的例子是断言语句(assert statements)。

请确保适当地缩进续行。

二元运算符前后应该换行吗?

几十年来,推荐的风格是在二元运算符之后换行。但这种做法可能以两种方式损害可读性:运算符倾向于分散在屏幕上的不同列上,并且每个运算符都与其操作数分开,移到了上一行。这样一来,眼睛需要额外的工作才能判断哪些项是相加的,哪些项是相减的:

# 错误的:
# 运算符与其操作数之间相隔太远

income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)

为了解决这个可读性问题,数学家及其出版商遵循相反的约定。唐纳德·克努斯(Donald Knuth)在他的《计算机与排版》系列中解释了这一传统规则:“虽然段落内的公式总是在二元运算和关系之后换行,但显示的公式总是在二元运算之前换行” [3]。

遵循数学的传统通常会使代码更具可读性:

# 正确的:
# 易于将运算符与操作数匹配

income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

在Python代码中,可以在二元运算符之前或之后进行换行,只要该约定在局部范围内保持一致即可。对于新代码,建议使用克努斯的风格。

空白行

使用两个空白行来包围顶层函数和类定义。

在类内部的方法定义之间使用一个空白行来分隔。

可以(但应谨慎使用)在相关函数组之间添加额外的空白行来分隔。对于一组相关的一行式代码(例如,一组虚拟实现),可以省略空白行。

在函数内部,应谨慎使用空白行来指示逻辑部分。

Python接受控制-L(即^L)换页符作为空白字符;许多工具将这些字符视为页面分隔符,因此您可以使用它们来分隔文件中相关部分的页面。请注意,某些编辑器和基于Web的代码查看器可能不识别控制-L作为换页符,并会在其位置显示另一个符号。

源文件编码

Python核心发布版中的代码应始终使用UTF-8编码,并且不应包含编码声明。

在标准库中,非UTF-8编码应仅用于测试目的。应谨慎使用非ASCII字符,最好仅用于表示地点和人名。如果非ASCII字符用作数据,请避免使用如“z̯̯͡a̧͎̺l̡͓̫g̹̲o̡̼̘”这样的嘈杂Unicode字符和字节顺序标记(BOM)。

Python标准库中的所有标识符必须使用仅ASCII的标识符,并且应尽可能使用英文单词(在许多情况下,会使用不是英文的缩写和技术术语)。

鼓励面向全球受众的开源项目采取类似的策略。

导入

导入语句通常应该单独成行:

# 正确的:
import os
import sys


# 错误的:
import sys, os

虽然,这样也可以:

# 正确的:
from subprocess import Popen, PIPE

导入语句总是放在文件的顶部,紧接在任何模块注释和文档字符串之后,但在模块的全局变量和常量之前。导入应该按照以下顺序分组:

  1. 标准库导入:首先导入Python标准库中的模块。
  2. 相关第三方库导入:然后导入与你的代码相关的第三方库模块。
  3. 本地应用/库特定导入:最后导入你的本地应用或库特有的模块。

你应该在每个导入组之间放置一个空行。

推荐使用绝对导入,因为它们通常更容易阅读,并且在导入系统配置不正确(例如,当包内的一个目录意外地出现在sys.path中时)时,它们往往表现更好(或者至少能给出更好的错误信息)。

import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example

然而,明确的相对导入是绝对导入的一个可接受的替代方案,尤其是在处理复杂的包布局时,使用绝对导入会过于冗长。

在这种情况下,使用相对导入(如from . import module或from .. import module)可以使得代码更加简洁,同时保持包结构的清晰。但请注意,相对导入的使用需要小心,以确保它们不会破坏包的封装性或引入意外的依赖关系。

from . import sibling
from .sibling import example

标准库代码应避免复杂的包布局,并始终使用绝对导入。

当从包含类的模块中导入类时,通常可以这样写:

from myclass import MyClass
from foo.bar.yourclass import YourClass

如果这种命名方式导致了局部名称冲突,那么应该显式地指定它们:

import myclass
import foo.bar.yourclass

并使用myclass.MyClass和foo.bar.yourclass.YourClass这样的形式

应避免使用通配符导入(from <module>  import *),因为它们会使命名空间中存在哪些名称变得不清晰,从而混淆读者和许多自动化工具。通配符导入有一个例外的用例,那就是作为公共API的一部分重新发布内部接口(例如,用来自可选加速器模块的定义覆盖接口的纯Python实现,并且具体哪些定义将被覆盖是事先不知道的)。

当以这种方式重新发布名称时,下面关于公共和内部接口的准则仍然适用。

注:在Python编程中,通配符导入(例如from module import *)通常不被推荐,因为它们会导入模块中定义的所有公共名称(不包括以单下划线_开头的名称),这可能会导致命名空间污染和名称冲突。此外,这种导入方式使得代码的阅读者难以快速了解哪些名称是从哪个模块导入的,增加了代码的理解难度。

然而,在某些特定情况下,通配符导入有其用武之地,比如当你需要作为一个公共API的一部分重新发布一个内部接口时。这种情况下,你可能需要覆盖某个接口的一个纯Python实现,用来自另一个模块(可能是可选的加速器模块)的更高效或更具体的实现来替换它。由于你事先可能不知道哪些定义会被覆盖,因此使用通配符导入可能是一个方便的选择。

但是,即使在这种情况下,你也应该谨慎使用通配符导入,并确保你的代码仍然遵循PEP 8中关于公共和内部接口的其他准则。例如,你应该清晰地文档化你的公共API,并确保内部实现细节不会泄露到公共API中。此外,你还应该考虑使用其他方法来重新发布接口,比如显式地导入和重命名所需的名称,或者使用更高级的模块组织策略来避免命名冲突和命名空间污染。

     相关文章:

PEP 8 – Python 代码风格指南中文版(一)

PEP 8 – Python 代码风格指南中文版(二)

PEP 8 – Python 代码风格指南中文版(三)

PEP 8 – Python 代码风格指南中文版(四)

PEP 8 – Python 代码风格指南中文版(五)

PEP 8 – Python 代码风格指南中文版(六)

PEP 8 – Python 代码风格指南中文版(七)

PEP 8 – Python 代码风格指南中文版(八)

PEP 8 – Python 代码风格指南中文版(九) 

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值