Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

Idioms and Anti-Idioms Question

 

 

Python python RSS feed   Index | Next | Previous | View Threaded


bcharrow at csail

Jun 21, 2009, 9:14 PM

Post #1 of 16 (594 views)
Permalink
Idioms and Anti-Idioms Question

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
--
http://mail.python.org/mailman/listinfo/python-list


steven at REMOVE

Jun 21, 2009, 10:51 PM

Post #2 of 16 (572 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

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
--
http://mail.python.org/mailman/listinfo/python-list


lie.1296 at gmail

Jun 21, 2009, 10:54 PM

Post #3 of 16 (571 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

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.
"""
--
http://mail.python.org/mailman/listinfo/python-list


ldo at geek-central

Jun 22, 2009, 1:01 AM

Post #4 of 16 (569 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

In message <H0F%l.20231$y61.5030[at]news-server.bigpond.net.au>, 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)
)


--
http://mail.python.org/mailman/listinfo/python-list


wbsoft at xs4all

Jun 22, 2009, 3:57 AM

Post #5 of 16 (567 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

Op maandag 22 juni 2009, schreef Lawrence D'Oliveiro:
> value = \
> (
> foo.bar()['first'][0] * baz.quux(1, 2)[5:9]
> +
> calculate_number(10, 20) * forbulate(500, 360)
> )

I' prefer:

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

w best regards,
Wilbert Berendsen

--
http://www.wilbertberendsen.nl/
"You must be the change you wish to see in the world."
-- Mahatma Gandhi

--
http://mail.python.org/mailman/listinfo/python-list


ldo at geek-central

Jun 22, 2009, 5:03 AM

Post #6 of 16 (565 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

In message <mailman.1941.1245668263.8015.python-list[at]python.org>, 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)
)


--
http://mail.python.org/mailman/listinfo/python-list


peter at www

Jun 22, 2009, 3:52 PM

Post #7 of 16 (554 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

On 2009-06-22, Lie Ryan <lie.1296[at]gmail.com> 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

--
Peter Billam www.pjb.com.au www.pjb.com.au/comp/contact.html
--
http://mail.python.org/mailman/listinfo/python-list


milesck at umich

Jun 22, 2009, 4:34 PM

Post #8 of 16 (553 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

On Jun 22, 2009, at 12:14 AM, Ben Charrow wrote:

> 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, along with one of those gotchas, a mix of tabs and spaces are
used such that the second line only _appears_ to have a different
level of indentation? ;)

-Miles

--
http://mail.python.org/mailman/listinfo/python-list


ldo at geek-central

Jun 23, 2009, 4:16 AM

Post #9 of 16 (537 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

In message <slrnh402pc.deb.peter[at]box8.pjb.com.au>, 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.

--
http://mail.python.org/mailman/listinfo/python-list


gagsl-py2 at yahoo

Jun 23, 2009, 8:24 AM

Post #10 of 16 (533 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

En Mon, 22 Jun 2009 20:34:40 -0300, Miles Kaufmann <milesck[at]umich.edu>
escribió:
> On Jun 22, 2009, at 12:14 AM, Ben Charrow wrote:
>
>> 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, along with one of those gotchas, a mix of tabs and spaces are
> used such that the second line only _appears_ to have a different level
> of indentation? ;)

Neither. As back in time as I can go (Python 1.5), having any character
after the backslash has always been a syntax error no matter what. Only
the error message has changed:

C:\TEMP>python15 syntaxerror.py
File "syntaxerror.py", line 18
value = foo.bar()['first'][0]*baz.quux(1, 2)[5:9] \
^
SyntaxError: invalid token

So the "it might be subtly wrong" argument is strongly wrong.

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list


pavlovevidence at gmail

Jun 23, 2009, 8:32 AM

Post #11 of 16 (533 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

On Jun 21, 9:14 pm, Ben Charrow <bchar...@csail.mit.edu> 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
--
http://mail.python.org/mailman/listinfo/python-list


jcd at sdf

Jun 23, 2009, 8:50 AM

Post #12 of 16 (534 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

On Mon, 2009-06-22 at 22:52 +0000, Peter Billam wrote:

> 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
>
> --
> Peter Billam www.pjb.com.au www.pjb.com.au/comp/contact.html


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

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



--
http://mail.python.org/mailman/listinfo/python-list


lie.1296 at gmail

Jun 23, 2009, 11:07 AM

Post #13 of 16 (527 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

Peter Billam wrote:
> On 2009-06-22, Lie Ryan <lie.1296[at]gmail.com> 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.
--
http://mail.python.org/mailman/listinfo/python-list


ldo at geek-central

Jun 30, 2009, 10:19 PM

Post #14 of 16 (446 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

In message <mailman.2018.1245772229.8015.python-list[at]python.org>, 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?

--
http://mail.python.org/mailman/listinfo/python-list


jcd at sdf

Jul 2, 2009, 7:15 AM

Post #15 of 16 (438 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

On Wed, 2009-07-01 at 17:19 +1200, Lawrence D'Oliveiro wrote:
> In message <mailman.2018.1245772229.8015.python-list[at]python.org>, 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?

--
http://mail.python.org/mailman/listinfo/python-list


ldo at geek-central

Jul 3, 2009, 5:08 PM

Post #16 of 16 (415 views)
Permalink
Re: Idioms and Anti-Idioms Question [In reply to]

In message <mailman.2493.1246544869.8015.python-list[at]python.org>, J. Cliff
Dyer wrote:

> On Wed, 2009-07-01 at 17:19 +1200, Lawrence D'Oliveiro wrote:
>>
>> In message <mailman.2018.1245772229.8015.python-list[at]python.org>, 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.

--
http://mail.python.org/mailman/listinfo/python-list

Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.