网站LOGO
博客 | 棋の小站
页面加载中
12月6日
达尔达尼亚瀑布,博洛尼亚,意大利 ...
网站LOGO 博客 | 棋の小站
记录学习,心得,状态,生活。
菜单
  • 热评
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    PEP8,Python开发的美工指导员
    点击复制本页地址
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    按住ctrl可打开默认菜单

    PEP8,Python开发的美工指导员

    · 原创 ·
    学学编程 · Python
    共 10891 字 · 约 9 分钟 · 459

    我最早了解PEP8时是在PyCharm的格式提醒中看到的。那时候初学Python语言,只知道Python由严格的缩进级别控制,也只是跟着老师敲代码的步伐一步一步模仿。我是在《Python从入门到精通》这本书上接触到Python。那时前几课的老师都是一个女老师。她那时候只是在IDLE上教如何敲代码,但是她的代码给人的感觉就是很工整,即使是纯手敲。因为她就遵从了PEP8规范之一——“#”注释要在该行代码最后一个字符后用两个空格隔开,且注释内容在“#”之后用一个空格隔开,即a = 1 # 注释xxx。代码的可读性的重要性不言而喻,而每个人对代码的工整程度都有不同的定义。因此kennethreitz就总结出了一套Python代码编写规范。此规范目前被大众所认可,也被广泛学习。PEP8官网为pep8.org,此文章会挑选此网站中比较常用的规范,分享给大家。

    代码布局

    缩进

    每个缩进级别使用4个空格。

    连续行应该使用Python在圆括号、方括号和大括号内的隐式行连接或使用悬挂缩进。垂直对齐包装的元素当使用悬挂缩进时,应考虑以下事项:第一行不应有任何参数,并且应使用进一步的缩进以清楚地将其本身区分为继续行。

    当函数参数列表过长而需要换行时,换到下一行的参数应与上一行的参数保持垂直对齐。若选择在第一个参数前就换行,则第一个参数前应缩进两个级别,以和参数下一行的代码缩进区分开。

    正确的缩进:

    python 代码:
    # Aligned with opening delimiter.
    foo = long_function_name(var_one, var_two,
                             var_three, var_four)
    
    # More indentation included to distinguish this from the rest.
    def long_function_name(
            var_one, var_two, var_three,
            var_four):
        print(var_one)
    
    # Hanging indents should add a level.
    foo = long_function_name(
        var_one, var_two,
        var_three, var_four)

    错误的缩进:

    python 代码:
    # Arguments on first line forbidden when not using vertical alignment.
    foo = long_function_name(var_one, var_two,
        var_three, var_four)
    
    # Further indentation required as indentation is not distinguishable.
    def long_function_name(
        var_one, var_two, var_three,
        var_four):
        print(var_one)

    可选择短于4空格的缩进。

    可选:

    python 代码:
    # Hanging indents *may* be indented to other than 4 spaces.
    foo = long_function_name(
      var_one, var_two,
      var_three, var_four)

    当if-语句的条件部分足够长,需要跨多行编写时,值得注意的是,两个字符的关键字(即if),加上一个空格,加上一个左括号,为多行条件的后续行创建了一个自然的4空格缩进。这可能会与嵌套在if-语句中的缩进代码套件产生视觉冲突,该代码套件自然也会缩进4个空格。该PEP没有明确说明如何(或是否)进一步在视觉上将这些条件行与if-语句内的嵌套套件区分开来。在这种情况下,可接受的选项包括但不限于:

    python 代码:
    # No extra indentation.
    if (this_is_one_thing and
        that_is_another_thing):
        do_something()
    
    # Add a comment, which will provide some distinction in editors
    # supporting syntax highlighting.
    if (this_is_one_thing and
        that_is_another_thing):
        # Since both conditions are true, we can frobnicate.
        do_something()
    
    # Add some extra indentation on the conditional continuation line.
    if (this_is_one_thing
            and that_is_another_thing):
        do_something()

    多行结构上的右大括号/括号/括号可以排列在列表最后一行的第一个非空白字符下面,如:

    python 代码:
    my_list = [
        1, 2, 3,
        4, 5, 6,
        ]
    result = some_function_that_takes_arguments(
        'a', 'b', 'c',
        'd', 'e', 'f',
        )

    或者它可以排列在开始多行结构的行的第一个字符之下,如:

    python 代码:
    my_list = [
        1, 2, 3,
        4, 5, 6,
    ]
    result = some_function_that_takes_arguments(
        'a', 'b', 'c',
        'd', 'e', 'f',
    )

    选择空格还是选择制表符

    空格是首选的缩进方法。

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

    最大行长度

    将所有行限制为最多79个字符。

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

    限制所需的编辑器窗口宽度可以使多个文件并排打开,并且在使用代码评审工具在相邻列中显示两个版本时效果很好。

    大多数工具中的默认包装会破坏代码的可视结构,使其更难理解。选择这些限制是为了避免在窗口宽度设置为80的编辑器中换行,即使换行时工具在最后一列中放置标记图示符。一些基于web的工具可能根本不提供动态换行。

    一些团队强烈喜欢更长的线长度。对于专门或主要由能够就此问题达成一致的团队维护的代码,可以将标称行长度从80个字符增加到100个字符(有效地将最大长度增加到99个字符),前提是注释和文档字符串仍然以72个字符包装。

    换行的首选方法是在圆括号、方括号和大括号内使用Python的隐含行延续。通过将表达式括在括号中,可以将长行拆分为多行。这些应该优先于使用反斜杠来继续行。

    反斜杠有时可能仍然是合适的。例如,长的多个with-语句不能使用隐式延续,所以反斜杠是可以接受的:

    python 代码:
    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())

    二元运算符在何处打破

    在Python代码中,允许在二元运算符之前或之后中断,只要约定在本地保持一致。对于新的代码,建议遵循Knuth的风格,即在运算符前打断。

    python 代码:
    # Yes: easy to match operators with operands
    income = (gross_wages
              + taxable_interest
              + (dividends - qualified_dividends)
              - ira_deduction
              - student_loan_interest)

    空白行

    用两个空行包围顶级函数和类定义。

    类中的方法定义由一个空行包围。

    额外的空白行可以用来(有节制地)分隔相关函数的组。在一堆相关的一行代码之间可以省略空行(例如一组虚拟实现)。

    在函数中尽量少用空行来表示逻辑部分。

    import导入

    若有多个导入则应该分行。

    正确:

    python 代码:
    import os
    import sys

    错误:

    python 代码:
    import os, sys

    但限定导入可以放在一行。

    正确:

    python 代码:
    from subprocess import Popen, PIPE

    导入总是放在文件的顶部,就在所有模块注释和文档字符串之后,在模块全局值和常量之前。

    导入应按以下顺序分组:

    1. 标准库导入
    2. 相关第三方进口
    3. 本地应用程序/库特定导入

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

    推荐使用绝对导入,因为它们可以使变量具有更好的可读性,也会有更少的错误提示。

    python 代码:
    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example

    若显式绝对导入过于冗余,可选用显式相对导入。

    python 代码:
    from . import sibling
    from .sibling import example

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

    隐式相对导入永远不应该使用,并且在Python 3中已经删除了。

    当从包含类的模块导入类时,通常可以拼写如下:

    python 代码:
    from myclass import MyClass
    from foo.bar.yourclass import YourClass

    若上方的导入会导致命名冲突,可以使用如下的导入方式:

    python 代码:
    import myclass
    import foo.bar.yourclass

    然后使用myclass.MyClassfoo.bar.yourclass.YourClass

    应该避免使用通配符导入(from import *),因为它们会使命名空间中出现的名称不清楚,从而使读者和许多自动化工具感到困惑。通配符导入有一个可辩护的用例,即将内部接口重新发布为公共API的一部分(例如,使用来自可选加速器模块的定义覆盖接口的纯Python实现,并且事先不知道哪些定义将被覆盖)。

    表达式和语句中的空格

    在以下情况下避免多余的空格:

    直接在圆括号、方括号或大括号内:

    正确:

    python 代码:
    spam(ham[1], {eggs: 2})

    错误:

    python 代码:
    spam( ham[ 1 ], { eggs: 2 } )

    在尾随逗号和后面的右括号之间:

    正确:

    python 代码:
    foo = (0,)

    错误:

    python 代码:
    bar = (0, )

    紧接逗号、分号或冒号之前:

    正确:

    python 代码:
    if x == 4: print x, y; x, y = y, x

    错误:

    python 代码:
    if x == 4 : print x , y ; x , y = y , x

    然而,在切片中冒号的作用就像一个二元运算符,并且应该在两侧具有相等的数量(将其视为具有最低优先级的运算符)。在扩展切片中,两个冒号必须应用相同的间距。例外:当省略切片参数时,空格将被省略。

    正确:

    python 代码:
    ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
    ham[lower:upper], ham[lower:upper:], ham[lower::step]
    ham[lower+offset : upper+offset]
    ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
    ham[lower + offset : upper + offset]

    错误:

    python 代码:
    ham[lower + offset:upper + offset]
    ham[1: 9], ham[1 :9], ham[1:9 :3]
    ham[lower : : upper]
    ham[ : upper]

    紧接在开始函数调用参数列表的左括号之前:

    正确:

    python 代码:
    spam(1)

    错误:

    python 代码:
    spam (1)

    紧接在开始索引或切片的左括号之前:

    错误:

    python 代码:
    dct['key'] = lst[index]

    错误:

    python 代码:
    dct ['key'] = lst [index]

    赋值(或其他)运算符周围有多个空格,用于将其与另一个运算符对齐。

    正确:

    python 代码:
    x = 1
    y = 2
    long_variable = 3

    错误:

    python 代码:
    x             = 1
    y             = 2
    long_variable = 3

    其他空格

    避免在任何地方尾随空白。因为它通常是不可见的,所以可能会令人困惑:例如,后面跟有空格和换行符的反斜杠不算作行继续标记。

    始终在这些二元运算符的两侧使用单个空格:赋值(=)、增广赋值(+=、-=等)、比较(==、<、>、!=、<>、<=、>=、in、not in、is、is not)、布尔(and、or、not)。

    正确:

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

    错误:

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

    如果使用具有不同优先级的运算符,请考虑在具有最低优先级的运算符周围添加空白。用你自己的判断;但是,永远不要使用一个以上的空格,并且始终在二元运算符的两边具有相同数量的空白。

    正确:

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

    错误:

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

    当用于指示关键字参数或默认参数值时,不要在=符号周围使用空格。

    正确:

    python 代码:
    def complex(real, imag=0.0):
        return magic(r=real, i=imag)

    错误:

    python 代码:
    def complex(real, imag = 0.0):
        return magic(r = real, i = imag)

    函数注释应该使用冒号的常规规则,并且在->箭头周围总是有空格(如果存在)。

    正确:

    python 代码:
    def munge(input: AnyStr): ...
    def munge() -> AnyStr: ...

    错误:

    python 代码:
    def munge(input:AnyStr): ...
    def munge()->PosInt: ...

    将参数注释与默认值组合时,在=符号周围使用空格(但仅适用于既有注释又有默认值的参数)。

    正确:

    python 代码:
    def munge(sep: AnyStr = None): ...
    def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

    错误:

    python 代码:
    def munge(input: AnyStr=None): ...
    def munge(input: AnyStr, limit = 1000): ...

    复合语句(同一行上的多个语句)通常不受欢迎。

    正确:

    python 代码:
    if foo == 'blah':
        do_blah_thing()
    do_one()
    do_two()
    do_three()

    错误:

    python 代码:
    if foo == 'blah': do_blah_thing()
    do_one(); do_two(); do_three()
    if foo == 'blah': do_blah_thing()
    for x in lst: total += x
    while t < 10: t = delay()
    if foo == 'blah': do_blah_thing()
    else: do_non_blah_thing()
    
    try: something()
    finally: cleanup()
    
    do_one(); do_two(); do_three(long, argument,
                                 list, like, this)
    
    if foo == 'blah': one(); two(); three()

    注释

    内联注释是与语句位于同一行的注释。内联注释应与语句至少用两个空格分隔。它们应该以#和一个空格开头。

    内联注释是不必要的,事实上,如果它们陈述了显而易见的东西,就会分散注意力。

    这样做毫无意义:

    python 代码:
    i = i + 1  # 将i的值增1

    注释应该多使用文档字符串。有关更多文档字符串的知识请阅读下面的文章。

    Python文档,高级Py注释
    学学编程 400 头像

    命名

    命名规则

    有以下几种常见的命名:

    • b (单个小写字母)
    • B (单个大写字母)
    • lowercase(小写英文单词)
    • lower_case_with_underscores(带下画线的小写单词)
    • UPPERCASE(全部大写)
    • UPPER_CASE_WITH_UNDERSCORES(带下画线的大写单词)
    • CapitalizedWords (or CapWords, CamelCase5, StudlyCaps)(驼峰命名法)
    • mixedCase (和 CapitalizedWords 区分开)
    • Capitalized_Words_With_Underscores (小丑命名)

    在CapWords中使用缩写时,请将缩写的所有字母大写。HTTPServerError比HttpServerError好。

    还有一种风格是使用一个简短的唯一前缀将相关名称分组在一起。这在Python中使用得不多,但为了完整性而提到它。例如,os.stat()函数返回一个元组,其项传统上具有诸如st_mode、st_size、st_mtime等的名称。(这样做是为了强调与POSIX系统调用struct的字段的对应关系,这有助于程序员熟悉它。

    此外,还可以识别以下使用前导或尾随下划线的特殊形式(这些形式通常可以与任何大小写约定组合使用):

    _single_leading_underscore:弱“内部使用”指示符。例如,from M import *不会导入名称以下划线开头的对象。

    single_trailing_underscore_:约定使用,避免与Python关键字冲突,例如:def f(class_=None)

    当一个用C或C++编写的扩展模块有一个附带的Python模块,提供更高级别的(例如更面向对象的)接口,C/C++模块具有前导下划线(例如:_socket)。

    类名

    类名通常应使用CapWords约定。

    在接口被记录并主要用作可调用的情况下,可以使用函数的命名约定。

    请注意,内置名称有一个单独的约定:大多数内建名称是单个单词(或两个单词一起运行),CapWords约定仅用于异常名称和内建常量。

    设计用于通过from M import *使用的模块应该使用__all__机制来防止导出全局变量,或者使用旧的约定,即在这些全局变量的前缀加上下划线(您可能希望这样做以表明这些全局变量是“模块非公共的”)。

    函数名

    函数名应该是小写的,必要时用下划线分隔单词,以提高可读性。

    mixedCase只允许在已经是流行风格的上下文中使用(例如threading.py),以保持向后兼容性。

    总是使用self作为实例方法的第一个参数。

    始终使用cls作为类方法的第一个参数。

    如果函数参数的名称与保留关键字冲突,通常最好在后面附加一个下划线,而不是使用缩写或拼写错误。class_比clss好。(也许更好的做法是使用同义词来避免这种冲突。

    常量

    常量通常在模块级别上定义,并以大写字母书写,下划线分隔单词。示例包括MAX_OVERFLOW和TOTAL。

    其他规范

    像None这样的单例比较应该总是用is或is not来完成,而不是相等运算符。

    此外,当你真正的意思是if x时,小心写if x is not None-例如。当测试默认值为None的变量或参数是否设置为其他值时。另一个值可能有一个类型(例如容器),在布尔上下文中可能是false!

    使用is not运算符而不是not ... is。虽然这两种表达在功能上相同,但前者更易于阅读,更推荐。

    正确:

    python 代码:
    if foo is not None:

    错误:

    python 代码:
    if not foo is None:

    当实现具有丰富比较的排序操作时,最好实现所有六个操作运算符的魔法函数(__eq__、__ne__、__lt__、__le__、__gt__、__ge__),而不是依赖于其他代码来执行特定的比较。有关魔法函数的文章请阅读下文。

    Python高级用法2——魔法函数
    学学编程 520 头像

    从Exception而不是BaseException导出异常。从BaseException的直接继承是为异常保留的,因为捕获它们几乎总是错误的。

    根据捕获异常的代码可能需要的区别来设计异常层次结构,而不是根据引发异常的位置。目的是回答问题“哪里出错了?

    一个空的except:子句将捕获SystemExit和KeyboardInterrupt异常,这使得使用Control-C中断程序变得更加困难,并且可以掩盖其他问题。如果你想捕获所有的异常,可以使用except Exception:(bare except相当于except BaseException:)。

    一个好的经验法则是将裸“except”子句的使用限制在两种情况下:

    1. 如果异常处理程序将打印或记录跟踪;至少用户将意识到错误已经发生。
    2. 如果代码需要做一些清理工作,但随后让异常向上传播raise。try...finally可以更好地处理这个问题。

    上下文管理器在执行获取和释放资源以外的操作时,都应该通过单独的函数或方法调用。举例来说:

    正确:

    python 代码:
    with conn.begin_transaction():
        do_stuff_in_transaction(conn)

    错误:

    python 代码:
    with conn:
        do_stuff_in_transaction(conn)
    声明:本文由 (博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。
    现在已有

    4

    条评论
    发一条!
    1. 头像
      TeacherDu
      • 等级:Lv.5
      • 角色:首页 · 好友
      • 在线:本周

      过来学习学习!

      · · · 北京-北京
      1. 头像
        TeacherDu

        学习学习!

        · · · 辽宁-沈阳
    2. 头像
      云晓晨
      • 等级:Lv.5
      • 角色:首页 · 好友
      • 在线:本周

      还没学python,不过开学就要学了

      · · · 山东-东营
      1. 头像
        云晓晨

        我的Python都是自学的,学校不教。

        · · · 辽宁-沈阳
    博客logo 博客 | 棋の小站 记录学习,心得,状态,生活。
    ICP 冀ICP备2023007665号 ICP 冀公网安备 13030202003453号

    🕛

    本站已运行 221 天 15 小时 45 分

    👁️

    今日访问量:480 昨日访问量:2564

    🌳

    建站:Typecho 主题:MyLife
    博客 | 棋の小站. © 2023 ~ 2023.
    网站logo

    博客 | 棋の小站 记录学习,心得,状态,生活。
     
     
     
     
    壁纸
     
     
     
     

    4

    1

  • 下一篇