定义具有太多参数的函数以遵守PEP8标准

Sud*_*fle 57 python pep8

我已经定义了一个带有很长参数列表的函数.定义中的总字符数大于80,不符合PEP8.

def my_function(argument_one, argument_two, argument_three, argument_four, argument_five):
Run Code Online (Sandbox Code Playgroud)

什么是避免水平滚动的最佳方法.

Bre*_*arn 79

PEP 8给出了一个例子:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
Run Code Online (Sandbox Code Playgroud)

这是官方的答案.就个人而言,我讨厌这种方法,其中连续行具有与任何真实缩进级别不对应的前导空格.我的方法是:

class Rectangle(Blob):

    def __init__(
        self, width, height,
        color='black', emphasis=None, highlight=0
    ):
Run Code Online (Sandbox Code Playgroud)

...或者让这条线超过80个字符.

  • 我实际上很困惑地在这两者之间做出选择.对于第一个,连续的行有任意的空格,这是我不喜欢的.第二个看起来很混乱成为一个功能.我更希望PEP8官方回答. (5认同)
  • 我发现你的第二个例子中的方法很脏.第一个宣言引起了我的注意,没有问题,而第二个宣言我必须仔细寻找它.特别是当有20种方法时,每种方法在同一类中有2-3行. (3认同)
  • 这与变脏无关,这与第二个示例中的方法实际上更实用有关。它允许编辑器对方法主体进行适当的代码折叠,同时允许您查看方法的参数。作者建议的官方数字与任何缩进级别都不对应。 (2认同)
  • 可能有点跑题了,但是有人知道在找到第一个解决方案时是否有办法强制 flake8 失败?我真的不喜欢它,即使它是标准的 PEP8,更喜欢第二种解决方案。 (2认同)

Phi*_*aro 21

1. 我会推荐什么

即使它使函数更加冗长,对于不止一个参数,我认为这是最好的——下面的例子来自Python——:

def my_function(
    argument_one, 
    argument_two, 
    argument_three,
    argument_four, 
    argument_five,
):
    ...
Run Code Online (Sandbox Code Playgroud)

2. 为什么?

  1. 将每个参数放在一行上使得使用git diffs变得非常简单,因为更改一个变量只会显示更改。如果每一行都有多个论点,那么后面会在视觉上更烦人。
    • 请注意,最后一个参数后面的尾随逗号使以后添加或删除参数更容易,同时也符合PEP 8 的尾随逗号约定,并在git diff以后产生更好的结果。
  2. 真的不喜欢“将参数与左括号对齐”范式的原因之一是它不会产生易于维护的代码
    • Kevlin Henney在他的 ITT 2016 - 许多程序员的七种无效编码习惯讲座(大约 17:08)中解释说这一种不好的做法。
    • 这是一个不好的做法的主要原因是,如果您更改函数的名称(或者它太长),您将不得不重新编辑所有参数行上的间距,这不是在所有可扩展的,虽然它可能(有时)(主观上)更漂亮。
    • 另一个原因,与上面的一个密切相关,是关于元编程。如果代码库变得太大,您最终会发现自己需要对代码文件本身进行编程更改,如果每个函数的参数间距不同,这可能会变得很糟糕
  3. 大多数编辑器,一旦打开括号并按下enter,将打开一个带有制表符的新行,并将右括号推到下一行,不带制表符。因此,以这种方式格式化代码非常快速且标准化。例如,这种格式在JavaScript和 中很常见Dart
  4. 最后,如果您认为每个参数都太笨拙,因为您的函数可能有很多参数,我会说由于罕见的例外,您正在损害代码的简单格式。
    • 不要通过例外来立法
    • 如果你的函数有很多参数,你可能做错了什么。将其分解为更多(子)函数和(子)类。

3. 无论如何...

一个好的约定好过一个坏的约定,但执行一个约定比对它们不必要地挑剔要重要得多

一旦您决定使用标准,请与您的同事分享您的决定并使用自动格式化程序——例如,PrettierJavaScriptin的流行选择VS Code;并且该Dart语言已经在全球范围内标准化了一个:dartfmt- 始终如一地执行它,减少手动编辑的需要。


Rot*_*eti 13

对于使用"输入"类型检查器的Python代码,我建议:

def some_func(
    foo: str,
    bar: str = 'default_string',
    qux: Optional[str] = None,
    qui: Optional[int] = None,
) -> List[str]:
    """
    This is an example function.
    """
    print(foo)
    ...
Run Code Online (Sandbox Code Playgroud)

恕我直言,当使用类型注释时,单行中具有多个参数的变体看起来非常混乱.所以我认为最好让它们各自独立.

如果您使用"yapf",则可以在以下选项中使用以下选项.style.yapf:

[style]
dedent_closing_brackets = true
split_arguments_when_comma_terminated = true
Run Code Online (Sandbox Code Playgroud)


kyl*_*e.a 10

def my_function(argument_one, argument_two, argument_three, 
                argument_four, argument_five):
Run Code Online (Sandbox Code Playgroud)


Ray*_*Luo 6

我个人也曾经想出过与@BrenBarn第二种风格相同的解决方案。我喜欢它能正确表示函数参数的缩进及其实现的方式,尽管“不高兴的表情”在某些其他人看来并不常见。

如今,PEP8专门提供了这种情况的示例,因此主流可能会采用这种样式:

# More indentation included to distinguish this from the rest.
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)
Run Code Online (Sandbox Code Playgroud)


Ben*_*Ben 5

我个人喜欢将参数从左括号开始一行一行地排列起来,并保持缩进。flake8似乎也对此感到满意。

def guess_device_type(device_name: str,
                      username: str=app.config['KEY_TACACS_USER'],
                      password: str=app.config['KEY_TACACS_PASS'],
                      command: str='show version') -> str:
    """Get a device_type string for netmiko"""
Run Code Online (Sandbox Code Playgroud)