PEP-8: clarify if multiline argument list with a closing `)` on a separate line is acceptable

As the issue has raised in several python projects (including pylint and black) I think PEP-8 would benefit from being a bit more precise

https://www.python.org/dev/peps/pep-0008/#indentation states

Continuation lines should align wrapped elements either vertically using Python’s implicit line joining inside parentheses, brackets and braces, or using a hanging indent [7]. When using a hanging indent the following should be considered; there should be no arguments on the first line and further indentation should be used to clearly distinguish itself as a continuation line.

and then gives two examples

in yes it gives :

foo = long_function_name(
    var_one, var_two,
    var_three, var_four)

(with 1 indentation)

and in no it gives

# Further indentation required as indentation is not distinguishable.
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

my question:

is

def long_function_name(
    var_one, var_two, var_three,
    var_four
):  # <----   it visually make clear that print is not inside the argument list , so it is now distinguishable
    print(var_one)

“possible” ?

especially if you see this other example

    # 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()

where a comment is given as possible way to have only 1 indentation

so at the very least the docstring should play the same role and allows :

def long_function_name(
    var_one, var_two, var_three,
    var_four
): 
    """The doc string is also a comment """ 
    print(var_one)

Personally, I use that style in some cases, when it’s more readable (to me, at least). I would be sad if style checker tools for some reason decided that rejecting such a style was OK.

Having said that, I don’t really care what the style is for the Python standard library itself (which is what PEP 8 is actually about, regardless of the fact that tools seem to think that it’s the “one true style” for all Python code) and I definitely don’t feel that it’s something where PEP 8 should pronounce one style as preferable over the other. Both have their places, and the programmer’s judgement should apply here (just as anywhere else, but again that seems to be a point that gets lost in “let the style checker set the rules” policies…)

3 Likes

exactly my feeling, I’m sorry if I haven’t expressed myself correctly, my goal was to make it clearer that both are correct i.e (and that pep-8 goal is readability more than one the defining the one true style) :slight_smile:

I think for this, just adding one more example in pep-8 examples maybe good enough ?

In such cases I prefer to use two indentation levels.

def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)
2 Likes

yes here it’s more about tackling the making it clearer that pep-8 allows both, rather than “which one do you prefer” (for which I understand that both side have rational arguments to prefer a given one), so I would prefer the discussion to focus more on "is the style in the first post an acceptable one per pep-8 ‘spirit’ , if so, can we add an example of such style in pep-8 in the acceptable examples, if not can we add it explicitly in the ‘no’ with the reason why it’s against pep-8 spirit.

Remember that PEP 8 is the style guide for Python itself, and while the community often times chooses to use it as their own style guide, it isn’t meant to cover all cases. So in this instance I would say it covers what it’s supported to with the one style we prefer in Python itself. Now that doesn’t say other styles aren’t equally as valid, it’s just that we don’t choose to use it.

3 Likes

So the root of this argument is that Black produces code that isn’t always in compliance with PEP 8. I say this is fine – if you use Black you don’t need PEP 8 to tell you how to format your code. (PEP 8 is still useful for other things like naming things.)

Black optimizes for a different goal than PEP 8; PEP 8 optimizes for readability while Black sometimes compromises readability in order to satisfy other goals such as minimizing lines changed as code evolves.

I don’t want to compromise PEP 8 though.

4 Likes

Thanks for your answer, yes the goal is not about saying that this given style should be how the stdlib should formatted (as anyway pep-8 permits several style).

Actually it was more about I’ve seen nothing in PEP-8 stating it was not compliant. Can you guide me to the line that makes it “invalid per pep-8” ? it’s not only about black, there’s other tool like pylint etc. where people were arguing about

def foo(
   bar,
   ter
):
   """my docstring"""
   print("something")

being not acceptable as pep-8.

However as pep-8 state

or it may be lined up under the first character of the line that starts the multiline construct, as in:

my_list = [
1, 2, 3,
4, 5, 6,
]
result = some_function_that_takes_arguments(
‘a’, ‘b’, ‘c’,
‘d’, ‘e’, ‘f’,
)

having ): on a separate line valid seems covered by it right ? and that this visual separation + docstring is enough to avoid the ambiguity (as per the if example above), makes it difficult to not seeing as being in the limit of pep-8 consider acceptable.

I would interpret the examples you quote as supporting the use of ): on a separate line, should the programmer wish to use that style. However, I would also be happy if someone said that PEP 8 takes no stance on this style.

Surely if someone wants to prohibit a particular style, then:

  1. They are entirely within their rights to do so in their own projects, regardless of what PEP 8 says.
  2. They have no authority to dictate what other projects choose to do, again regardless of PEP 8.

If someone wants to assert that PEP 8 prohibits this style, then (a) the burden is upon them to demonstrate where PEP 8 makes that assertion, and (b) it seems to me like a pointless waste of their time to make that assertion, given the 2 points above.

The only borderline case is tools like pycodestyle, that do style checking for projects, which may need to interpret PEP 8 fairly strictly to implement a “PEP 8 conformant” style. But debates about how they choose to interpret PEP 8 are really a matter for them - if their users disagree with their interpretation, they can add flags to allow the users to modify the base style, document their interpretation, or whatever they choose.

2 Likes

I would prefer PEP 8 to explicitly discourage putting ): on a line by itself, since I find it ugly, Black notwithstanding. This is different from putting the last bracket of a tuple, list or call on a line by itself, since there’s nothing following that’s indented relative to the start of the construct.

3 Likes

The trick with style guides is the potential list of unacceptable formats is nearly infinite while documenting what is acceptable is tractable. So assume if something is not listed as acceptable then it isn’t :wink:.

haha, for that specific quote I was more talking about definitions rather than examples , for which I agree with you , you can’t list them all (maybe provide the generator function :slight_smile: )

thanks to all of you for the clear and straight to the point discussion. I guess I got the clarification I wanted, even though it didn’t go the way I would have preferred :slight_smile: the key learning I got from there

  1. pep-8 has always been for “internal use” and is not meant to be enforced outside, that some people follow it outside and some preach it as the “one true way” is an unintended consequence.
  2. ): though at first ambiguous from my reading, was actually not in the mind of those who written pep-8, therefore should not be considered as pep-8 compliant.
  3. some of the prominent members of python community sees no issue with black enforcing a different code-style as long as it’s outside of python official projects.

thanks again for taking the time to answering me.

1 Like

Sorry to jump in when the thread is a few days old, but I don’t see that anyone else has mentioned these points:

As I recall, every example in PEP 8 that has the closing delimiter on the following line also has a trailing comma after the last element, and vice versa - indeed, “no trailing comma on the same line except for single-element tuples” is an explicitly stated rule. I had taken the reverse (comma required if the delimiter is on its own line) to therefore also be an implicit rule. Maybe it would be worth discussing explicitly?

Also, no-one has mentioned return annotations. Placing a line break before the closing parenthesis is the only way to place the return annotation on a line by itself without resorting to a backslash line continuation. Placing the line break between ) -> or after -> results in a syntax error.

1 Like