views:

182

answers:

7

I am aware that the standard Python convention for line width is 79 characters. I know lines can be continued in a number of ways, such as automatic string concatenation, parentheses, and the backslash. What does not seem to be as clearly defined is how exactly the overflowing text should be formatted. Do I push it all the way back to col 1? To the col where the original line starts? To the start of the parentheses (if applicable)? For example, say I have something like this:


        self.someLongAttributeName = {'someLongKeyName':'someLongValueName',
                                      'anotherLongKeyName':'anotherLongValueName'}

Supposing that the format I used above would fit the 79 character limit, is the indentation of the second line correct?

Now suppose that the first line as shown above is > 79 characters. How should things look in that case?

NOTE: I know that a lot of people disagree with the 79-character convention. While I respect that there are a lot of pros and cons to each side of the issue, this debate is not relevant to my question. I am asking how to follow the convention, not whether or not I should, so please do not espouse the advantages of abandoning it in your reply. Thanks. =)

+5  A: 

http://www.python.org/dev/peps/pep-0008/ See Maximum Line Length

Limit all lines to a maximum of 79 characters.

There are still many devices around that are limited to 80 character lines; plus, limiting windows to 80 characters makes it possible to have several windows side-by-side. The default wrapping on such devices disrupts the visual structure of the code, making it more difficult to understand. Therefore, please limit all lines to a maximum of 79 characters. For flowing long blocks of text (docstrings or comments), limiting the length to 72 characters is recommended.

The preferred way of wrapping long lines is by using Pythons 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. Some examples:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if width == 0 and height == 0 and \
           color == 'red' and emphasis == 'strong' or \
           highlight > 100:
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)
Manux
+2  A: 

In PEP 8 there is an example:

class Rectangle(Blob):

    def __init__(self, width, height,
        # more code
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

Which, to my eye, suggests that your example is correct. I think you should break first line of the example after opening bracket ( { ) like so:

    self.someLongAttributeName = {
                 'someLongKeyName':'someLongValueName',
                 'anotherLongKeyName':'anotherLongValueName'
    }

if it is too long. I don't know if it is 'pythonic', but should be familiar and readable.

cji
A: 

I was pretty sure this was answered here before, but I can't find it now so..

The short answer is that PEP8 does not cover how to format object literals, other than that colons should have zero spaces before and one space after.

I do them like this:

obj = {
     'foo': 1,
     'bar': 2,
     'bas': 3,
}
Triptych
+9  A: 

Supposing that the format I used above would fit the 79 character limit, is the indentation of the second line correct?

Yes, that's how PEP 8 shows it in examples:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if width == 0 and height == 0 and \
           color == 'red' and emphasis == 'strong' or \
           highlight > 100:
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

But when the opening parenthesis/brace is already close to the 79th column, I usually just exploit this:

Two good reasons to break a particular rule:

(1) When applying the rule would make the code less readable, even for
    someone who is used to reading code that follows the rules.
[...]

And do something like

self.some_long_attribute_name = {
    'someLongKeyName': 'someLongValueName',
    'anotherLongKeyName': 'anotherLongValueName'
}

or

long_object_name.do_something_with_long_name(
    long_expression_returning_is_first_arg,
    long_expression_returning_is_second_arg
)
delnan
+1  A: 

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.

Matt Williamson
+3  A: 

Even beyond Python, I do this all the time for my C code so I can (as the PEP says) have 2-3 files open on a monitor side-by-side and see them all.

The backslash operator \ works as a line continuation operator in Python as well as C, but I prefer to try to group lines with parenthesis () or braces {} (or brackets [] for Python lists), whatever is most convenient. If I decide I want to add another line in the middle of a long continuing block, I don't want to worry about any stupid 'gotchas': missing a \ or worse, some errant space after the \ invalidating the continuation.

For long conditionals, I like to double-indent so it's more obvious that that code isn't part of the new block.

if (somethingLong == x or
        somethingElse == y or
        somethingOld == z or
        x < y < z or
        doIt.now()):
    pass
Nick T
A: 

Good trick is also to do like this:

my_long_string="""
This are
many lines of text
"""

a = [a in my_long_string.split() if a]

Some people prefer to use \ after opening triple quote and not filter empty lines, but I really hate those beasts.

For your particular example I agree with cji.

Tony Veijalainen
.split() splits on all whitespace, not just newlines
recursive