Как удалить дополнительный отступ в тройных цитируемых многострочных строках Python?
У меня есть редактор python, где пользователь вводит script или код, который затем помещается в основной метод за кулисами, а также имеет каждую строку с отступом. Проблема в том, что если у пользователя есть строка с несколькими строками, отступ, сделанный в целом script, влияет на строку, вставляя вкладку в каждое пространство. Проблема script была бы такой простой, как:
"""foo
bar
foo2"""
Итак, когда в основном методе это будет выглядеть так:
def main():
"""foo
bar
foo2"""
и теперь строка будет иметь дополнительную вкладку в начале каждой строки.
Ответы
Ответ 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'