为Flake8编写代码

维护者 Flake8 不出所料,对于项目中维护的代码样式有一些看法。

在撰写本文时, Flake8 启用PyCodeStyle的所有检查、PyFlakes的所有检查,并将最大复杂性值(对于McCabe)设置为10。除此之外,我们还通过PyDocStyle(仅禁用D203)和使用flake8 import order的Google的import order样式强制执行PEP-0257样式的文档字符串。

最后两个有点不寻常,所以我们在下面提供示例。

PEP-0257样式文档字符串

Flake8 尝试记录内部接口以及我们的API和doc字符串提供了一种非常方便的方法。即使函数、类或方法没有特别包含在我们的文档中,最好还是使用doc字符串。此外, Flake8 具有一些PyDocStyle未检查的样式首选项。

例如,虽然大多数人不会读取 flake8.main.git.hook() 这个doc字符串仍然为维护者和未来的协作者提供了价值。它们(非常明确地)描述了函数的用途,它做了什么,接受什么参数以及返回什么。

# src/flake8/main/git.py
def hook(lazy=False, strict=False):
    """Execute Flake8 on the files in git's index.

    Determine which files are about to be committed and run Flake8 over them
    to check for violations.

    :param bool lazy:
        Find files not added to the index prior to committing. This is useful
        if you frequently use ``git commit -a`` for example. This defaults to
        False since it will otherwise include files not in the index.
    :param bool strict:
        If True, return the total number of errors/violations found by Flake8.
        This will cause the hook to fail.
    :returns:
        Total number of errors found during the run.
    :rtype:
        int
    """
    # NOTE(sigmavirus24): Delay import of application until we need it.
    from flake8.main import application
    app = application.Application()
    with make_temporary_directory() as tempdir:
        filepaths = list(copy_indexed_files_to(tempdir, lazy))
        app.initialize(['.'])
        app.options.exclude = update_excludes(app.options.exclude, tempdir)
        app.options._running_from_vcs = True
        app.run_checks(filepaths)

    app.report_errors()
    if strict:
        return app.result_count
    return 0

注意,因为参数 hookstrict 是简单的布尔参数,我们内联这些参数的类型声明,例如。,

:param bool lazy:

还要注意的是,我们从一个新行开始描述参数,并缩进了4个空格。

另一方面,我们也在一些名称稍长的地方分离参数类型声明,例如。,

# src/flake8/formatting/base.py
def format(self, error):
    """Format an error reported by Flake8.

    This method **must** be implemented by subclasses.

    :param error:
        This will be an instance of :class:`~flake8.style_guide.Error`.
    :type error:
        flake8.style_guide.Error
    :returns:
        The formatted error string.
    :rtype:
        str
    """

我们分开了 :param error::type error: .

遵循上面的示例和指导原则,可以帮助您编写风格正确的doc字符串 Flake8 .

进口

Flake8 遵循Google在Python风格指南中发布的导入指南。简而言之,这包括:

  • 仅导入模块

  • 将导入分组到

    • 标准库导入

    • 第三方依赖项导入

    • 本地应用程序导入

  • 按字母顺序排列导入

实际上,这看起来像:

import configparser
import logging
from os import path

import requests

from flake8 import exceptions
from flake8.formatting import base

因此,在上述情况下,我们不:

  • 将对象导入命名空间以使其可从该命名空间访问

  • 只导入我们正在使用的对象

  • 添加注释,说明导入是标准库模块或其他模块

其他风格偏好

最后, Flake8 有一些其他风格偏好,但目前还不能自动执行。

多行函数/方法调用

当您发现自己必须将对函数或方法的调用拆分为多行时,请在左括号后插入新行,例如。,

# src/flake8/main/options.py
add_option(
    '-v', '--verbose', default=0, action='count',
    parse_from_config=True,
    help='Print more information about what is happening in flake8.'
         ' This option is repeatable and will increase verbosity each '
         'time it is repeated.',
)

# src/flake8/formatting/base.py
def show_statistics(self, statistics):
    """Format and print the statistics."""
    for error_code in statistics.error_codes():
        stats_for_error_code = statistics.statistics_for(error_code)
        statistic = next(stats_for_error_code)
        count = statistic.count
        count += sum(stat.count for stat in stats_for_error_code)
        self._write('{count:<5} {error_code} {message}'.format(
            count=count,
            error_code=error_code,
            message=statistic.message,
        ))

在第一个示例中,我们将几个参数都放在一行,然后单独添加最后两个参数。在第二个示例中,每个参数都有自己的行。这条规则有点主观。一般的想法是,每行放置一个参数是首选的,但有时将几个参数组合在一行上是合理和可以理解的。

评论

如果你要添加重要的评论,一定要签名。在 Flake8 我们通常在评论前面加上 NOTE(<name>) . 例如,

# NOTE(sigmavirus24): The format strings are a little confusing, even
# to me, so here's a quick explanation:
# We specify the named value first followed by a ':' to indicate we're
# formatting the value.
# Next we use '<' to indicate we want the value left aligned.
# Then '10' is the width of the area.
# For floats, finally, we only want only want at most 3 digits after
# the decimal point to be displayed. This is the precision and it
# can not be specified for integers which is why we need two separate
# format strings.
float_format = '{value:<10.3} {statistic}'.format
int_format = '{value:<10} {statistic}'.format

伊恩在大多数网站上都很有名 sigmavirus24 所以他就这样签了字。

动词属于函数名

Flake8 更喜欢函数中有动词。如果你正在写一个函数,返回一个文件生成器,那么 generate_files 总是比 make_filesfiles .