Idioms and Anti-Idioms Question

Discussion in 'Python' started by Ben Charrow, Jun 22, 2009.

  1. Ben Charrow

    Ben Charrow Guest

    I have a question about the "Using Backslash to Continue Statements" in the
    howto "Idioms and Anti-Idioms in Python"
    (http://docs.python.org/howto/doanddont.html#using-backslash-to-continue-statements)


    It says:

    "...if the code was:

    value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    + calculate_number(10, 20)*forbulate(500, 360)

    then it would just be subtly wrong."

    What is subtly wrong about this piece of code? I can't see any bugs and can't
    think of subtle gotchas (e.g. the '\' is removed or the lines become separated,
    because in both cases an IndentationError would be raised).

    Cheers,
    Ben
     
    Ben Charrow, Jun 22, 2009
    #1
    1. Advertising

  2. On Mon, 22 Jun 2009 00:14:50 -0400, Ben Charrow wrote:

    > I have a question about the "Using Backslash to Continue Statements" in
    > the howto "Idioms and Anti-Idioms in Python"
    > (http://docs.python.org/howto/doanddont.html#using-backslash-to-

    continue-statements)
    >
    >
    > It says:
    >
    > "...if the code was:
    >
    > value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    > + calculate_number(10, 20)*forbulate(500, 360)
    >
    > then it would just be subtly wrong."
    >
    > What is subtly wrong about this piece of code? I can't see any bugs and
    > can't think of subtle gotchas (e.g. the '\' is removed or the lines
    > become separated, because in both cases an IndentationError would be
    > raised).



    As examples go, it's pretty lousy because you can't just copy and paste
    it into an interpreter session and see for yourself. However, with some
    helper objects:


    def forbulate(*args):
    return [1]

    def calculate_number(*args):
    return 2

    class K: pass

    foo = K()
    foo.bar = lambda: {'first': [1, 2, 3]}
    baz = K()
    baz.quux = lambda *args: [3]*10

    value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    + calculate_number(10, 20)*forbulate(500, 360)


    I can run the example. I confirm that it works without a space after the
    line continuation character. Using Python 2.5, if I put a space after the
    backslash I get

    SyntaxError: unexpected character after line continuation character

    followed by

    IndentationError: unexpected indent


    So I don't understand the claim that the code is "subtly wrong" either.
    It looks to me like it's obviously wrong.



    --
    Steven
     
    Steven D'Aprano, Jun 22, 2009
    #2
    1. Advertising

  3. Ben Charrow

    Lie Ryan Guest

    Ben Charrow wrote:
    > I have a question about the "Using Backslash to Continue Statements" in
    > the howto "Idioms and Anti-Idioms in Python"
    > (http://docs.python.org/howto/doanddont.html#using-backslash-to-continue-statements)
    >
    >
    > It says:
    >
    > "...if the code was:
    >
    > value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    > + calculate_number(10, 20)*forbulate(500, 360)
    >
    > then it would just be subtly wrong."
    >
    > What is subtly wrong about this piece of code? I can't see any bugs and
    > can't think of subtle gotchas (e.g. the '\' is removed or the lines
    > become separated, because in both cases an IndentationError would be
    > raised).


    The preferred style is to put the binary operators before the line-break
    (i.e. the line break is after the operators):

    value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] + \
    calculate_number(10, 20)*forbulate(500, 360)

    and even more preferrable is NOT to use explicit line break at all;
    relying on implicit breaking with parentheses since then you won't need
    to worry about empty lines:

    value = (foo.bar()['first'][0]*baz.quux(1, 2)[5:9] +
    calculate_number(10, 20)*forbulate(500, 360)
    )

    although, in a formula that is so complex, the most preferable way is to
    separate them so they won't need to take more than a single line:

    a = foo.bar()['first'][0]
    b = baz.quux(1, 2)[5:9]
    c = calculate_number(10, 20)
    d = forbulate(500, 360)
    value = a*b + c*d

    of course, a, b, c, d should be substituted with a more helpful names.

    The following is an extract from PEP 8:

    """
    The preferred way of wrapping long lines is by using Python's implied
    line continuation inside parentheses, brackets and braces. If
    necessary, you can add an extra pair of parentheses around an
    expression, but sometimes using a backslash looks better. Make sure to
    indent the continued line appropriately. The preferred place to break
    around a binary operator is *after* the operator, not before it.
    """
     
    Lie Ryan, Jun 22, 2009
    #3
  4. In message <H0F%l.20231$>, Lie Ryan
    wrote:

    > The preferred style is to put the binary operators before the line-break
    > ...


    Not by me. I prefer using a two-dimensional layout to make the expression
    structure more obvious:

    value = \
    (
    foo.bar()['first'][0] * baz.quux(1, 2)[5:9]
    +
    calculate_number(10, 20) * forbulate(500, 360)
    )

    In this case it's not necessary, but if the factors were really long, this
    could become

    value = \
    (
    foo.bar()['first'][0]
    *
    baz.quux(1, 2)[5:9]
    +
    calculate_number(10, 20)
    *
    forbulate(500, 360)
    )
     
    Lawrence D'Oliveiro, Jun 22, 2009
    #4
  5. In message <>, Wilbert
    Berendsen wrote:

    > I' prefer:
    >
    > value = (foo.bar()['first'][0] * baz.quux(1, 2)[5:9] +
    > calculate_number(10, 20) * forbulate(500, 360))


    I prefer using a two-dimensional layout to make the expression
    structure more obvious:

    value = \
    (
    foo.bar()['first'][0] * baz.quux(1, 2)[5:9]
    +
    calculate_number(10, 20) * forbulate(500, 360)
    )

    In this case it's not necessary, but if the factors were really long, this
    could become

    value = \
    (
    foo.bar()['first'][0]
    *
    baz.quux(1, 2)[5:9]
    +
    calculate_number(10, 20)
    *
    forbulate(500, 360)
    )
     
    Lawrence D'Oliveiro, Jun 22, 2009
    #5
  6. In message <>, Peter Billam wrote:

    > Damian Conway, in Perl Best Practices, puts forward a clear argument
    > for breaking *before* the operator:


    Except in JavaScript, where you have no choice.
     
    Lawrence D'Oliveiro, Jun 23, 2009
    #6
  7. Ben Charrow

    Carl Banks Guest

    On Jun 21, 9:14 pm, Ben Charrow <> wrote:
    > I have a question about the "Using Backslash to Continue Statements" in the
    > howto "Idioms and Anti-Idioms in Python"
    > (http://docs.python.org/howto/doanddont.html#using-backslash-to-contin...)
    >
    > It says:
    >
    > "...if the code was:
    >
    > value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    >          + calculate_number(10, 20)*forbulate(500, 360)
    >
    > then it would just be subtly wrong."
    >
    > What is subtly wrong about this piece of code?  I can't see any bugs and can't
    > think of subtle gotchas (e.g. the '\' is removed or the lines become separated,
    > because in both cases an IndentationError would be raised).


    Perhaps it was originally was like this:

    value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    + calculate_number(10, 20)*forbulate(500, 360)


    Carl Banks
     
    Carl Banks, Jun 23, 2009
    #7
  8. On Tue, 23 Jun 2009 11:50:06 -0400, "J. Cliff Dyer"
    <> declaimed the following in
    gmane.comp.python.general:


    > >>> spam = 6
    > >>> spam +

    > File "<stdin>", line 1
    > spam +
    > ^
    > SyntaxError: invalid syntax
    > >>> + spam

    > 6
    > >>>


    Except in actual code you are likely to get a syntax error from the
    lack of matching brackets or whatever is being used to indicate
    multiline continuation...
    -=-=-=-=-
    velveeta = 7
    spam = 6
    dinner = (spam

    + velveeta
    -=-=-=-=-
    E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>junk.py
    File "E:\UserData\Dennis Lee Bieber\My Documents\Python
    Progs\junk.py", line 8

    ^
    SyntaxError: invalid syntax

    E:\UserData\Dennis Lee Bieber\My Documents\Python Progs>

    --
    Wulfraed Dennis Lee Bieber KD6MOG

    HTTP://wlfraed.home.netcom.com/
    (Bestiaria Support Staff: )
    HTTP://www.bestiaria.com/
     
    Dennis Lee Bieber, Jun 23, 2009
    #8
  9. Ben Charrow

    Lie Ryan Guest

    Peter Billam wrote:
    > On 2009-06-22, Lie Ryan <> wrote:
    >> Ben Charrow wrote:
    >>> value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
    >>> + calculate_number(10, 20)*forbulate(500, 360)
    >>> What is subtly wrong about this piece of code? I can't see any bugs and
    >>> can't think of subtle gotchas (e.g. the '\' is removed or the lines
    >>> become separated, because in both cases an IndentationError would be
    >>> raised).

    >> The preferred style is to put the binary operators before the line-break
    >> (i.e. the line break is after the operators):
    >> value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] + \
    >> calculate_number(10, 20)*forbulate(500, 360)
    >> ...
    >> The following is an extract from PEP 8:
    >> The preferred way of wrapping long lines is by using Python's
    >> implied line continuation inside parentheses, brackets and braces.
    >> If necessary, you can add an extra pair of parentheses around an
    >> expression, but sometimes using a backslash looks better. Make sure to
    >> indent the continued line appropriately. The preferred place to break
    >> around a binary operator is *after* the operator, not before it.

    >
    > Damian Conway, in Perl Best Practices, puts forward a clear argument
    > for breaking *before* the operator:
    > Using an expression at the end of a statement gets too long,
    > it's common practice to break that expression after an operator
    > and then continue the expression on the following line ...
    > The rationale is that the operator that remains at the end
    > of the line acts like a continutation marker, indicating that
    > the expression continues on the following line.
    > Using the operator as a continutation marker seems like
    > an excellent idea, but there's a serious problem with it:
    > people rarely look at the right edge of code.
    > Most of the semantic hints in a program - such as keywords -
    > appear on the left side of that code. More importantly, the
    > structural cues for understanding code - for example, indenting, -
    > are predominantly on the left as well ... This means that indenting
    > the continued lines of the expression actually gives a false
    > impression of the underlying structure, a misperception that
    > the eye must travel all the way to the right margin to correct.
    >
    > which seems to me well-argued. I wonder on what grounds PEP8
    > says "The preferred place to break around a binary operator is
    > *after* the operator" ?
    > Perhaps it's just the "continutation marker" rationale?
    >
    > Regards, Peter
    >


    When you're *scanning* the code, breaking the line before the operator
    might be better since you can easily see that that a line is a
    continuation from the previous line.

    However, when it comes to *reading* the code, it's easy to miss that the
    code continues to the next line, especially when you rely on
    parentheses' implicit line continuation and don't use an explicit
    line-continuation character (i.e. \).

    So... IMHO when it comes to break before or after the operator, it
    depends on whether you rely on parentheses or explicit line
    continuation. If you use implicit continuation with parentheses, it's
    better to break after operators; else if you use explicit continuation
    with \, it's better to break before operators.

    Since python prefers using parentheses' implicit line cont., it follows
    that breaking after operator is the natural choice.
     
    Lie Ryan, Jun 23, 2009
    #9
  10. In message <>, J. Cliff
    Dyer wrote:

    > If the lines got separated, a leading + could disappear into its line
    > without any errors showing up. A trailing + would raise a syntax error.


    Unless, of course, it was moved onto the previous line as part of whatever
    caused the separation of the lines. How would you guard against that?
     
    Lawrence D'Oliveiro, Jul 1, 2009
    #10
  11. On Wed, 2009-07-01 at 17:19 +1200, Lawrence D'Oliveiro wrote:
    > In message <>, J. Cliff
    > Dyer wrote:
    >
    > > If the lines got separated, a leading + could disappear into its line
    > > without any errors showing up. A trailing + would raise a syntax error.

    >
    > Unless, of course, it was moved onto the previous line as part of whatever
    > caused the separation of the lines. How would you guard against that?
    >


    Can you give an example of what you mean?
     
    J. Cliff Dyer, Jul 2, 2009
    #11
  12. In message <>, J. Cliff
    Dyer wrote:

    > On Wed, 2009-07-01 at 17:19 +1200, Lawrence D'Oliveiro wrote:
    >>
    >> In message <>, J.
    >> Cliff Dyer wrote:
    >>
    >> > If the lines got separated, a leading + could disappear into its line
    >> > without any errors showing up. A trailing + would raise a syntax
    >> > error.

    >>
    >> Unless, of course, it was moved onto the previous line as part of
    >> whatever caused the separation of the lines. How would you guard against
    >> that?

    >
    > Can you give an example of what you mean?


    Sure. Just start with an example of what you mean.
     
    Lawrence D'Oliveiro, Jul 4, 2009
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eli Bendersky
    Replies:
    9
    Views:
    701
    Allan Herriman
    Apr 7, 2006
  2. Mark Rae
    Replies:
    0
    Views:
    634
    Mark Rae
    Mar 7, 2006
  3. Replies:
    9
    Views:
    672
    Carl Friedrich Bolz
    Feb 5, 2006
  4. Steven Watanabe

    Question about idioms for clearing a list

    Steven Watanabe, Jan 31, 2006, in forum: Python
    Replies:
    65
    Views:
    1,161
    Bryan Olson
    Feb 10, 2006
  5. itaj sherman
    Replies:
    39
    Views:
    1,140
    Larry Evans
    Feb 25, 2011
Loading...

Share This Page