PEP8 - Contradiction between E129 and E127/E128
Asked Answered
M

3

19

According to the PEP standards, indents should come before binary operators. Furthermore, multiline conditions should be enclosed within parentheses to avoid using backslashes before newlines. These two conventions lead to the following situation

if (long_condition_1
    or long_condition_2):
    do_some_function()

This code in turn breaks E129 visually indented line with same indent as next logical line in PEP8. However, the second line must be indented exactly four spaces, as otherwise it breaks E128 or E127 for under-indented or over-indented lines.

How should one format the above so that it confirms to PEP8 standards?

Monthly answered 19/6, 2017 at 19:12 Comment(11)
I don't know whether this will pass the automatic checker nor do I know if this is considered the Correct Solution, but what I've done sometimes is put three or four extra spaces in between the 'if' and the '(', and then indent the continued condition lines to match.Juvenile
That does actually conform to the standards. Apparently E127 and E128 check against the position of the grouping parentheses, not the indentation of the previous line.Monthly
@tdelaney This isn't a duplicated because that question deals with E125. The accepted answer for that question fails E127 for over-indented visual indents and also conforms to the outdated W503, which is deprecated as described here.Monthly
@Juvenile While that does conform to E127, E128, and the intended W503, it fails E271 multiple spaces after keyword.Monthly
@JonClaus - running this code and the referenced code on my pep8 both result in E129 errors and changing the indents fixes them both. This code is acceptable in the pep8 style guide (_ This PEP takes no explicit position on how (or whether) to further visually distinguish such conditional lines from the nested suite inside the if -statement_) but run afoul of the pep8 script. That seems to change from time to time. I'm not sure why it triggered differently, but the answer is the normal way this problem is solved, hence my recommendation as a dup. I'm happy to undup it though.Wichern
@Wichern Yes, the linked answer passes PEP8 but that is only because PEP8 has an error with checking for binary operators, described in the issue I linked. Multiline expressions with binary operators should place them at the beginning of lines, not at the end.Monthly
That's a place where the style guide and checker script are in direct opposition. Move the 'or' to the line above and the warning goes away, but that is not the choice I would make. I thought you complaint was about under/over indented lines. Those errors don't happen with my run of pep8. The style guide suggests an extra indentation to visually separate the condition from the following block of code. The linked question solved the problem that way. That's about all I have to say about it!Wichern
I think it suggests using if(long_condition_1 instead of if (long_condition_1 on the first line.Leonoraleonore
@Leonoraleonore That does manage to pass all checks. Still, I don't feel like it's ideal. Both PEP and Google always have a space between their keywords and parentheses, although it's not an explicit requirement.Monthly
In the very first section of PEP 8, titled "A Foolish Consistency is the Hobgoblin of Little Minds", it says "However, know when to be inconsistent". Further down in the "Indentation" section, it discusses this specific problem, but takes no position and then lists a few options its considers acceptable. Note, too, this related anecdote.They're all referring, I believe, to Emerson's philosophy of self-reliance—in other words, decide for yourself.Leonoraleonore
I edited W503 out of the title because it appears to be a red herring -- you get the same indentation for continuation lines as for the body of the condition, and thus an inability to satisfy E127, E128, and E129 simultaneously, whether or not the continuation lines start with a binary operator.Juvenile
S
12

This should work properly

if (long_condition_1 or
       long_condition_2):
    do_some_function()
Shafting answered 26/4, 2018 at 11:40 Comment(2)
Works but looks horrible.Il
If you deindent long_condition_2 line then it looks even worse. You have to actually scan the last collumn for where the two dots are. People with any vision impairment (let's face it, this either already includes you, or will include, in 10-15 years) will have a hard time reading it.Maxa
B
8

The answer to this question has changed over time. Due to a change in stance from PEP8, W503 is now widely regarded to go against PEP8.

PEP8 now says it's fine to break before OR after, but to keep it consistent locally.

For newer code, Knuth-style is preferred (which I think refers to breaking before the operator).

if (
    long_condition_1
    or long_condition_2
    or (
        long_condition_3
        and long_condition4
    )
):
    do_some_function()
Blacking answered 21/1, 2019 at 22:45 Comment(2)
W503 appears to be a red herring: the issue is having the continuation lines for the conditional be indented to the same visual depth as the body of the if, whether or not they begin with an operator. Your example addresses this by putting the closing ): at the depth of the if keyword, which I like, but does it pass the automated style checker?Juvenile
My linters have been happy with this :)Blacking
D
3
if any((long_condition_1,
        long_condition_2)):
    do_some_function()

it's better to read when both conditions aligned too ...

Drus answered 24/8, 2021 at 17:45 Comment(2)
This seems to be the nicest solution. I'd prefer an explicit or, but breaking the line after the or as suggested in the highest-voted answer is just ugly in my opinion.Frech
In terms of execution, this is very different: this will build a tuple, evaluating all expressions in it, and then loop through it for falsy values. There is no short-circuiting and it's harder for the compiler to optimize.Antibiosis

© 2022 - 2024 — McMap. All rights reserved.