Подтвердить что ты не робот

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

У меня есть редактор python, где пользователь вводит script или код, который затем помещается в основной метод за кулисами, а также имеет каждую строку с отступом. Проблема в том, что если у пользователя есть строка с несколькими строками, отступ, сделанный в целом script, влияет на строку, вставляя вкладку в каждое пространство. Проблема script была бы такой простой, как:

"""foo
bar
foo2"""

Итак, когда в основном методе это будет выглядеть так:

def main():
    """foo
    bar
    foo2"""

и теперь строка будет иметь дополнительную вкладку в начале каждой строки.

4b9b3361

Ответ 1

Итак, если я получу его правильно, вы берете все, что вводит пользователь, отступают правильно и добавляют его в остальную часть вашей программы (а затем запускают всю эту программу).

Итак, после ввода пользователя в вашу программу вы можете запустить регулярное выражение, которое в основном возвращает этот принудительный отступ. Что-то вроде: в трех кавычках замените все "новые маркеры строк", а затем четыре пробела (или вкладку) только с "новым маркером строки".

Ответ 2

textwrap.dedent из стандартной библиотеки есть, чтобы автоматически отменить сумасшедший отступ.

Ответ 3

Из того, что я вижу, лучшим ответом здесь может быть inspect.cleandoc, который делает большую часть того, что делает textwrap.dedent, но также устраняет проблемы, которые textwrap.dedent имеет с лидирующей линией.

В приведенном ниже примере показаны различия:

>>> import textwrap
>>> import inspect
>>> x = """foo bar
    baz
    foobar
    foobaz
    """
>>> inspect.cleandoc(x)
'foo bar\nbaz\nfoobar\nfoobaz'
>>> textwrap.dedent(x)
'foo bar\n    baz\n    foobar\n    foobaz\n'
>>> y = """
...     foo
...     bar
... """
>>> textwrap.dedent(y)
'\nfoo\nbar\n'
>>> inspect.cleandoc(y)
'foo\nbar'
>>> z = """\tfoo
bar\tbaz
"""
>>> textwrap.dedent(z)
'\tfoo\nbar\tbaz\n'
>>> inspect.cleandoc(z)
'foo\nbar     baz'

Обратите внимание, что inspect.cleandoc также расширяет внутренние вкладки до пробелов. Это может быть неуместно для одного варианта использования, но отлично работает для меня.

Ответ 4

То, что следует за первой строкой многострочной строки, является частью строки и не рассматривается как отступ парсером. Вы можете свободно писать:

def main():
    """foo
bar
foo2"""
    pass

и он будет поступать правильно.

С другой стороны, это невозможно прочитать, и Python это знает. Поэтому, если docstring содержит пробелы во второй строке, это количество пробелов удаляется, когда вы используете help() для просмотра docstring. Таким образом, help(main) и help(main2) ту же справочную информацию.

def main2():
    """foo
    bar
    foo2"""
    pass

Ответ 5

Единственный способ, который я вижу - это разбить первые n вкладок для каждой строки, начиная со второй, где n - это известное определение основного метода.

Если эта идентификация неизвестна заранее - вы можете добавить конечную новую строку перед ее вставкой и удалить количество вкладок из последней строки...

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

Думайте, что есть лучшее решение.

Ответ 6

Показываю разницу между textwrap.dedent и inspect.cleandoc с большей ясностью:

Поведение с ведущей частью без отступа

import textwrap
import inspect

string1="""String
with
no indentation
       """
string2="""String
        with
        indentation
       """
print('string1 plain=' + repr(string1))
print('string1 inspect.cleandoc=' + repr(inspect.cleandoc(string1)))
print('string1 texwrap.dedent=' + repr(textwrap.dedent(string1)))
print('string2 plain=' + repr(string2))
print('string2 inspect.cleandoc=' + repr(inspect.cleandoc(string2)))
print('string2 texwrap.dedent=' + repr(textwrap.dedent(string2)))

Выход

string1 plain='String\nwith\nno indentation\n       '
string1 inspect.cleandoc='String\nwith\nno indentation\n       '
string1 texwrap.dedent='String\nwith\nno indentation\n'
string2 plain='String\n        with\n        indentation\n       '
string2 inspect.cleandoc='String\nwith\nindentation'
string2 texwrap.dedent='String\n        with\n        indentation\n'

Поведение с ведущей ролью с отступом

string1="""
String
with
no indentation
       """
string2="""
        String
        with
        indentation
       """

print('string1 plain=' + repr(string1))
print('string1 inspect.cleandoc=' + repr(inspect.cleandoc(string1)))
print('string1 texwrap.dedent=' + repr(textwrap.dedent(string1)))
print('string2 plain=' + repr(string2))
print('string2 inspect.cleandoc=' + repr(inspect.cleandoc(string2)))
print('string2 texwrap.dedent=' + repr(textwrap.dedent(string2)))

Выход

string1 plain='\nString\nwith\nno indentation\n       '
string1 inspect.cleandoc='String\nwith\nno indentation\n       '
string1 texwrap.dedent='\nString\nwith\nno indentation\n'
string2 plain='\n        String\n        with\n        indentation\n       '
string2 inspect.cleandoc='String\nwith\nindentation'
string2 texwrap.dedent='\nString\nwith\nindentation\n'