Правильный отступ для многострочных строк Python - PullRequest
414 голосов
/ 24 марта 2010

Какой правильный отступ для многострочных строк Python внутри функции?

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

или

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

или что-то еще?

В первом примере выглядит странно, что строка висит вне функции.

Ответы [ 12 ]

427 голосов
/ 24 марта 2010

Вы, вероятно, хотите выстроиться в линию с """

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

Поскольку новые строки и пробелы включены в саму строку, вам придется постобработать ее. Если вы не хотите этого делать, и у вас есть много текста, вы можете сохранить его отдельно в текстовом файле. Если текстовый файл не подходит для вашего приложения и вы не хотите выполнять постобработку, я бы, вероятно, выбрал

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

Если вы хотите постобработать многострочную строку, чтобы обрезать ненужные детали, вам следует рассмотреть модуль textwrap или метод постобработки строк документации, представленный в PEP 257 * * 1013

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)
233 голосов
/ 24 марта 2010

Функция textwrap.dedent позволяет начать с правильного отступа в источнике , а затем удалить его из текста перед использованием.

Компромисс, как отмечали некоторые другие, заключается в том, что это дополнительный вызов функции для литерала; примите это во внимание при решении, где разместить эти литералы в вашем коде.

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)

Завершающий \ в литерале сообщения журнала должен гарантировать, что разрыв строки не находится в литерале; таким образом, литерал не начинается с пустой строки, а начинается со следующей полной строки.

Возвращаемое значение из textwrap.dedent является входной строкой, в которой удалены все общие начальные пробельные отступы в каждой строке строки. Таким образом, вышеуказанное значение log_message будет:

Prepare to frobnicate:
Here it comes...
    Any moment now.
And: Frobnicate!
25 голосов
/ 05 января 2018

Использовать inspect.cleandoc примерно так:

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

Относительный отступ будет сохраняться, как и ожидалось.

Примечание: Рекомендуется делать отступ логических блоков кода в его связанном контексте для уточнения структуры. Например. многострочная строка, принадлежащая переменной string.

22 голосов
/ 03 октября 2015

Один из вариантов, который, по-видимому, отсутствует в других ответах (упоминается только в комментариях naxa):

def foo():
    string = ("line one\n"          # Add \n in the string
              "line two"  "\n"      # Add "\n" after the string
              "line three\n")

Это позволит правильно выравнивать, неявно соединять линии и сохранять сдвиг строк, что, для меня, является одной из причин, по которой я все равно хотел бы использовать многострочные строки.

Это не требует никакой постобработки, но вам нужно вручную добавить \n в любом месте, где вы хотите, чтобы строка заканчивалась. Либо в строке или в виде отдельной строки после. Последний легче скопировать-вставить.

17 голосов
/ 30 мая 2013

Еще несколько опций. В Ipython с включенным pylab dedent уже находится в пространстве имен. Я проверил, и это из Matplotlib. Или это может быть импортировано с:

from matplotlib.cbook import dedent

В документации говорится, что она быстрее, чем эквивалентная textwrap, и в моих тестах на ipython она действительно в среднем в 3 раза быстрее с моими быстрыми тестами. Он также имеет то преимущество, что отбрасывает все начальные пустые строки, что позволяет вам быть гибким при построении строки:

"""
line 1 of string
line 2 of string
"""

"""\
line 1 of string
line 2 of string
"""

"""line 1 of string
line 2 of string
"""

Использование отступа matplotlib в этих трех примерах даст тот же разумный результат. Функция dedent textwrap будет иметь начальную пустую строку с первым примером.

Очевидным недостатком является то, что textwrap находится в стандартной библиотеке, а matplotlib - внешний модуль.

Некоторые компромиссы здесь ... функции dedent делают ваш код более читабельным, когда строки определены, но требуют обработки позже, чтобы получить строку в пригодном для использования формате. В строках документации очевидно, что вы должны использовать правильный отступ, так как большинство использований строки документации выполнят требуемую обработку.

Когда мне нужна недлинная строка в моем коде, я нахожу следующий заведомо уродливый код, где я позволяю длинной строке выпасть из вмещающего отступа. Определенно не подходит «Красивое лучше, чем некрасивое», но можно утверждать, что оно проще и более явное, чем альтернатива dedent.

def example():
    long_string = '''\
Lorem ipsum dolor sit amet, consectetur adipisicing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip.\
'''
    return long_string

print example()
5 голосов
/ 25 ноября 2015

Если вы хотите быстрое и простое решение и избавите себя от ввода новых строк, вместо этого вы можете выбрать список, например ::

def func(*args, **kwargs):
    string = '\n'.join([
        'first line of very long string and',
        'second line of the same long thing and',
        'third line of ...',
        'and so on...',
        ])
    print(string)
    return
4 голосов
/ 09 марта 2016

Я предпочитаю

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

или

    def method():
        string = """\
line one
line two
line three\
"""
3 голосов
/ 10 апреля 2016

Мои два цента, выходите из конца строки, чтобы получить отступы:

def foo():
    return "{}\n"\
           "freq: {}\n"\
           "temp: {}\n".format( time, freq, temp )
1 голос
/ 08 марта 2018

Первый вариант - хороший, с отступом. Это в стиле Python - обеспечивает читабельность кода.

Для правильного отображения:

print string.lstrip()
1 голос
/ 29 марта 2012

Я пришел сюда в поисках простого однострочного удаления / исправления уровня идентификации строки документации для печати, , не делая его неопрятным , например, сделав его висеть вне функции "внутри скрипта.

Вот что я в итоге сделал:

import string
def myfunction():

    """
    line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print str(string.replace(myfunction.__doc__,'\n\t','\n'))[1:] 

Очевидно, что если вы делаете отступ с пробелами (например, 4), а не с клавишей табуляции, используйте что-то вроде этого:

print str(string.replace(myfunction.__doc__,'\n    ','\n'))[1:]

И вам не нужно удалять первый символ, если вы хотите, чтобы строки документации выглядели так:

    """line 1 of docstring
    line 2 of docstring
    line 3 of docstring"""

print string.replace(myfunction.__doc__,'\n\t','\n') 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...