45

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?

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
ann.piv
  • 681
  • 1
  • 7
  • 17
  • 4
    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 instead – anthony sottile Oct 05 '19 at 00:34
  • This seems like a good suggestion: https://github.com/mila-iqia/cookiecutter-pyml/issues/10#issuecomment-672041692 – Gaurav Srivastava Feb 09 '23 at 05:12

6 Answers6

30

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)
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
18

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.

L3viathan
  • 26,748
  • 2
  • 58
  • 81
2

instead and or or you can use all or any:

if all((
        this_is_one_thing,
        that_is_another_thing)):
    do_something()
vlk
  • 2,581
  • 3
  • 31
  • 35
  • This might not have been the best answer for everybody, but in my case it was. So +1 – Mihail-Cosmin Munteanu Aug 26 '22 at 09:51
  • That would need to be `all([this_is_one_thing, that_is_another_thing])`; `all` requires a single iterable, not multiple arguments. – chepner Dec 15 '22 at 12:43
  • @chepner: yes, look again, there is a `tuple` – vlk Feb 12 '23 at 20:45
  • 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 https://gist.github.com/dormeiri/0cd9a8868f125d6f9f4156b859f4899e – Dor Meiri Mar 02 '23 at 13:42
  • 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. – Denise Skidmore May 23 '23 at 16:57
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.

Denise Skidmore
  • 2,286
  • 22
  • 51
  • Note, the latest version of flake does not have this conflict at all, so that's another route to take: https://www.flake8rules.com/rules/W504.html – Denise Skidmore May 24 '23 at 16:09
-1

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.

Foxy Fox
  • 403
  • 6
  • 13
-1

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!!
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129