tags:

views:

641

answers:

4

What is the proper indentation for Python multiline strings within a function?

    def method():
        string = """line one
line two
line three"""

or

    def method():
        string = """line one
        line two
        line three"""

or something else?

It looks kind of weird to have the string hanging outside the function in the first example.

Thanks.

+1  A: 

I agree the 2nd one looks better, but the white space is included in the string unfortunately, so you'll end up with indents on the 2nd and 3rd line.

Davy8
A: 

It depends on how you want the text to display. If you want it all to be left-aligned then either format it as in the first snippet or iterate through the lines left-trimming all the space.

Ignacio Vazquez-Abrams
The way docstring-processing tools work is to remove not *all* the space on the left, but *as much* as the first indented line. This strategy is a bit more sophisticated and allows for you to indent and have it respected in the postprocessed string.
Mike Graham
+11  A: 

The textwrap.dedent function allows one to start with correct indentation in the source, and then strip it from the text before use.

import textwrap

def frobnicate(param):
    """ Frobnicate the scrognate param.

        The Weebly-Ruckford algorithm is employed to frobnicate
        the scrognate to within an inch of its life.

        """
    prepare_the_comfy_chair(param)
    log_message = textwrap.dedent("""\
        Prepare to frobnicate:
        Here it comes...
        Any moment now.
        And: Frobnicate!""")
    weebly(param, log_message)
    ruckford(param)

The return value from textwrap.dedent is the input string with all common leading whitespace indentation removed on each line of the string, meaning that the above log_message value will be flush left.

bignose
That's a snazzy solution right there!
jathanism
+5  A: 

You probably want to line up with the """

def foo():
    string = """line one
             line two
             line three"""

Since the newlines and spaces are included in the string itself, you will have to postprocess it. If you don't want to do that and you have a whole lot of text, you might want to store it separately in a text file. If a text file does not work well for your application and you don't want to postprocess, I'd probably go with

def foo():
    string = ("this is an "
              "implicitly joined "
              "string")

If you want to postprocess a multiline string to trim out the parts you don't need, you should consider the textwrap module or the technique for postprocessing docstrings presented in PEP 257:

def trim(docstring):
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = sys.maxint
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < sys.maxint:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return '\n'.join(trimmed)
Mike Graham
It's good to have the same level of indentation for each line of text in the string. But that means that the lines of text should be a single indentation level in (4 columns), not starting at some arbitrary many-columns-along position from the previous line.
bignose
@bignose, I do not see how that requirement helps to keep code cleaner or more readable or has any particular advantage.
Mike Graham
This is the ‘hanging indent’ style of line continuation. It is prescribed in PEP8 for purposes like function definitions and long if statements, though not mentioned for multiline strings. Personally this is one place I refuse to follow PEP8 (and use 4-space indenting instead), as I strongly dislike hanging indents, which for me obscure the proper structure of the program.
bobince