[Python-ideas] PEP8 operator must come before line break

Nathaniel Smith njs at pobox.com
Thu Apr 14 20:45:10 EDT 2016


On Thu, Apr 14, 2016 at 12:28 PM, Joseph Martinot-Lagarde <
contrebasse at gmail.com> wrote:
> Guido van Rossum <guido at ...> writes:
>
>> My rationale for this rule is that ending a line in a binary operator
>> is a clear hint to the reader that the line isn't finished. (If you
>> think about it, a comma is a kind of binary operator, and you wouldn't
>> move the comma to the start of the continuation line, would you?
>
> I personally tend to look more at the start of the lines because that's
> where the blocks are defined (by indentation). Also the end of the lines
are
> usually not aligned which makes binary operators harder to see.
> Because of these two reasons I always put binary operator at the start of
> new lines, because that's where I have the most chance to see them, and
I'm
> in favor of changing this in PEP8.

This is the case that jumped to mind for me as well...

If I saw code like this in a code review I'd force the author to change it
because the style is outright misleading:

return (something1() +
        a * b +
        some_other_thing() ** 2 -
        f -
        normalizer)

We're summing a list of items with some things being negated, but that
structure is impossible to see, and worst of all, the association between
the operator and the thing being operated on is totally lost. OTOH if we
write like this:

return (something1()
        + a * b
        + some_other_thing() ** 2
        - f
        - normalizer)

then the list structure is immediately obvious, and it's immediately
obvious which terms are being added and which are being subtracted.

Similarly, who can even tell if this code is correct:

return (something1() +
        a * b +
        some_other_thing() ** 2 -
        f /
        normalizer)

but if the same code is formatted this way then it's immediately obvious
that the code is buggy:

return (something1()
        + a * b
        + some_other_thing() ** 2
        - f
        / normalizer)

It should be corrected to:

return ((something1()
         + a * b
         + some_other_thing() ** 2
         - f)
        / normalizer)

(I'm calling the final item "normalizer" because this pattern actually
comes up fairly often in bayesian computations -- if you're working in log
space then at the end of some computation you subtract off a magic
normalizing factor, and if you're working in linear space then at the end
you divide off a magic normalizing factor. You can also get a similar
pattern for chains of * and /, though it's less common.)

In all of these cases, the hanging indent makes the fact that we have a
continuation line obvious from across the room -- I don't need help knowing
that there's a continuation, I need help figuring out what the the
computation actually does :-).

I actually find a similar effect for and/or chains, where the
beginning-of-line format makes things lined up and easier to scan -- e.g.
comparing these two options:

return (something1() and
        f() and
        some_expression > 1 and
        (some_other_thing() == whatever or
         blahblah or
         asdf))

return (something1()
        and f()
        and some_expression > 1
        and (some_other_thing() == whatever
             or blahblah
             or asdf))

then I find the second option dramatically more readable. But maybe that's
just me -- for and/or the argument is a bit less compelling, because you
don't regularly have chains of different operators with the same
precedence, like you do with +/-.

I guess this might have to do with a more underlying stylistic difference:
as soon as I have an expression that stretches across multiple lines, I try
to break it into pieces where each line is a meaningful unit, even if this
doesn't produce the minimum number of lines. For example I generally avoid
writing stuff like:

return (something1() and f() some_expression > 1 and
        (some_other_thing() == whatever or blahblah or asdf))

return (something1() + a * b + some_other_thing() ** 2 -
        f - normalizer)

-n

BIKESHEDDING REDUCTION ACT NOTICE: I hereby swear that I have said
everything useful I have to say about this topic and that this will be my
only contribution to this thread unless someone addresses me directly.

-- 
Nathaniel J. Smith -- https://vorpus.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160414/ecb7a7a5/attachment-0001.html>


More information about the Python-ideas mailing list