What is the recommended way to break a long if statement? (W504 line break after binary operator)
Asked Answered
G

6

47

What is currently the recommended way to break a long line of if statement with "and" and "or" operators?

1st option

With the style below (which is from PEP8) with flake8, I'm getting warnings: W504 line break after binary operator:

if (this_is_one_thing and
    that_is_another_thing):
    do_something()

2nd option

if (this_is_one_thing
    and that_is_another_thing):
    do_something()

Now, I'm getting the warning W503 line break before the binary operator. The second seems to be in line with this recommendation from PEP8

I tried to find an answer but I'm still unsure. I think maybe using 2nd option and disabling the W503 warning will be a way to deal with this problem?

Graphy answered 17/7, 2019 at 10:58 Comment(2)
I suspect you're using ignore= which will override the default ignore (which contains both codes because they are contradictory). you may find extend-ignore= useful insteadHeist
This seems like a good suggestion: github.com/mila-iqia/cookiecutter-pyml/issues/…Veracity
A
32

If we consult the documentation on flake 8 we see:

Anti-pattern

Note: Despite being in the anti-pattern section, this will soon be considered the best practice.

income = (gross_wages
          + taxable_interest)

Best practice

Note: Despite being in the best practice section, this will soon be considered an anti-pattern.

income = (gross_wages +
          taxable_interest)

So the line break before the binary operator will be considered best practice.

The documentation for W504, advices the operator before the new line as best practice, without the given note:

Anti-pattern

income = (gross_wages +
          taxable_interest)

Best practice

income = (gross_wages
          + taxable_interest)
Arboreous answered 17/7, 2019 at 11:4 Comment(2)
And this is why you should never trust a linterRafaelrafaela
So it's impossible to satisfy Flake8 if there is ever a line-break and a binary operator. This is very troublesome if you are required to run Flake8 as part of pre-merge CI check!!!Rambling
L
19

When in doubt, ask Black:

if (                                                           
    this_is_one_thing
    and that_is_another_thing
):                                                             
    do_something()                                             

For a long time, PEP-8 recommended breaking after a binary operator, but they have "recently" switched to the Donald-Knuth-approved break-before-binary-operator style.

Luce answered 17/7, 2019 at 11:5 Comment(0)
D
2

instead and or or you can use all or any:

if all((
        this_is_one_thing,
        that_is_another_thing)):
    do_something()
Dumond answered 18/3, 2022 at 7:46 Comment(5)
This might not have been the best answer for everybody, but in my case it was. So +1Wheelock
That would need to be all([this_is_one_thing, that_is_another_thing]); all requires a single iterable, not multiple arguments.Alacrity
@chepner: yes, look again, there is a tupleDumond
This is not equivalent to using or, because in any functions will get called no matter what is the value of proceeding items. While in or, it will evaluate the value once there is a single True-ish gist.github.com/dormeiri/0cd9a8868f125d6f9f4156b859f4899eElliottellipse
It works, but is this the tail wagging the dog? Are you using all because it's the clearest code for this job or because PEP8 and Flake8 are in disagreement? Coding standards are supposed to make the code clearer, not force you to jump through unnecessary hoops. I'm not saying it's a bad solution, if I had more than 3 operands I'd consider it too, but it's not the simple and straightforward way to express a 2 operand and.Ileum
I
0

Ultimately, when there are conflicts between coding standards, it is a team decision which standard your team will follow. Some teams come up with their own standard if the code base or several lead developers have a standard that predates the current standards, or a cross-lingual team wants to use the same standard in every language.

PEP8 is promoted by python.org, so I'd consider it the default for a new team and new code base, and if developing solo it would be the most portable standard to learn for when contributing to open source or future jobs.

So my team disabled W503 in flake8 config when we ran into the same issue. I believe pylint doesn't have the same problem, we're considering switching but are not yet ready for the additional level of scrutiny.

Ileum answered 23/5, 2023 at 17:10 Comment(1)
Note, the latest version of flake does not have this conflict at all, so that's another route to take: flake8rules.com/rules/W504.htmlIleum
G
-2

Flake8 is one of the Python lints, and the full list of errors can be found useful to find anti-patterns and best practices for each specific error.

Geese answered 3/5, 2022 at 11:47 Comment(0)
P
-2

Normally, I use backslashes for a if statement with multiple conditions in multiple lines as shown below because it work properly without any errors and warnings and it is simple and the readability is good:

exam1 = 70
exam2 = 60
exam3 = 50
                                   # ↓ Here
if (100 >= exam1 and exam1 >= 60) or \
   (100 >= exam2 and exam2 >= 60) or \
   (100 >= exam3 and exam3 >= 60): # ↑ Here
    print("You passed!!")

Output:

You passed!!
Parka answered 15/12, 2022 at 12:29 Comment(1)
This doesn't answer the question of breaking before or after the operand, which will break either flake8 or PEP8 standards.Ileum

© 2022 - 2024 — McMap. All rights reserved.