Как написать очень длинную строку, которая соответствует PEP8 и предотвращает E501

203

Как PEP8 предлагает придерживаться правила 80 столбцов для вашей программы на Python, как я могу соблюдать это с длинными строками, т.е.

s = "this is my really, really, really, really, really, really, really long string that I'd like to shorten."

Как бы я расширил это до следующей строки, т.е.

s = "this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten."
Федерер
источник

Ответы:

116

Неявная конкатенация может быть самым чистым решением:

s = "this is my really, really, really, really, really, really," \
    " really long string that I'd like to shorten."

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

Майкл Данн
источник
4
Вот почему я чувствовал себя идиотом, отправляющим вопрос. Приветствия.
Федерер
8
Это продолжение строки, выход за пределы конечной линии, а не просто неявная конкатенация, и до недавнего времени она явно запрещена в PEP8, хотя теперь есть допуск, но НЕ для длинных строк. Ответ Тодда ниже верен.
Аарон Холл
4
Мне нравится PEP8, но это часть PEP8, которая мне не нравится. Я чувствую, что неявное продолжение яснее из-за возможности путаницы с кортежами
monknomo
1
Помните , чтобы не добавлять пробелы после \
Мринал Саурабх
Что делать, если длинная строка находится в середине длинной многострочной строки?
Тейн
299

Кроме того, поскольку соседние строковые константы автоматически объединяются, вы также можете кодировать это так:

s = ("this is my really, really, really, really, really, really, "  
     "really long string that I'd like to shorten.")

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

Лично мне не нравятся обратные слеши, и я вспоминаю, что читал где-то, что его использование на самом деле не рекомендуется в пользу этой формы, которая более явна Помните: «Явное лучше, чем неявное».

Я считаю, что обратный слеш менее понятен и менее полезен, потому что на самом деле он экранирует символ новой строки. Нельзя ставить комментарий в конце строки после него, если это необходимо. Это можно сделать с помощью константных строковых констант:

s = ("this is my really, really, really, really, really, really, " # comments ok
     "really long string that I'd like to shorten.")

Я использовал поиск Google «длина строки python», который возвращает ссылку PEP8 в качестве первого результата, а также ссылки на другой хороший пост StackOverflow на эту тему: « Почему Python PEP-8 должен указывать максимальную длину строки в 79 символов? »

Другой хорошей поисковой фразой будет «продолжение строки Python».

Тодд
источник
8
+1: «Лично мне не нравятся обратные слеши, и я вспоминаю, что читал где-то, что его использование на самом деле не рекомендуется в пользу этой формы, которая является более явной. Помните:« Явный лучше, чем неявный ».»
Альберто Мегия,
13
Для всех, кто получает кортеж и задается вопросом, почему. Не добавляйте запятые в конце строк, это приведет к кортежу, а не к строке. ;)
bugmenot123
7
Разве добавление символа + не является более явным, чем в данном примере? Я все еще считаю это неявным. то есть, "str1" + "str2"а не"str1" "str2"
user1318135
4
Я на самом деле согласен, что знак плюс является более явным, но это делает другое. Он превращает строку в выражение для оценки, вместо того, чтобы указывать одну строковую константу в нескольких частях. Я не уверен, но я думаю, что это делается во время синтаксического анализа, тогда как выражение необходимо выполнить позже. Разница в скорости, вероятно, незначительна, если их не существует огромное количество. Но также с эстетической точки зрения я предпочитаю автоматическую конкатенацию, так как это на один беспорядочный символ на строку.
Тодд
4
Этот синтаксис также сохраняет возможность применения строкового форматирования, например:('this is my really, really, really, really, really long {} ' 'that I'd really, really, really, like to {}').format(var1, var2))
Тим
16

Я думаю, что самым важным словом в вашем вопросе было «предлагает».

Стандарты кодирования это забавные вещи. Часто руководство, которое они предоставляют, имеет действительно хорошую основу, когда оно было написано (например, большинство терминалов не могут отображать> 80 символов в строке), но со временем они становятся функционально устаревшими, но при этом строго соблюдаются. Я думаю, что вам нужно сделать здесь, взвесить относительные достоинства «ломки» этого конкретного предложения по сравнению с читабельностью и удобством сопровождения вашего кода.

Извините, это не дает прямого ответа на ваш вопрос.

ZombieSheep
источник
Я абсолютно согласен. Существует похожее правило стиля Java, которое тоже устарело (IMHO).
Икер Хименес
Да, я согласен, однако я ломал голову над тем, как бы я следовал этому в этом конкретном примере. Я всегда стараюсь, чтобы классы, методы не превышали 80 символов, однако я бы сказал, что такая строка не имеет никакого эффекта, кроме, возможно, отрицательного.
Федерер
1
Вам также необходимо сопоставить ваши личные предпочтения с общепринятым стандартом кодирования. Вы хотите, чтобы новые люди могли приходить и чувствовать себя комфортно с форматированием кода с первого дня.
откат
1
Я сам знаю, что я склонен придерживаться ограничения в 80 символов только потому, что я все еще делаю большую часть своего кодирования в IDLE, и мне не нравится, как он обрабатывает горизонтальную прокрутку. (Нет полосы прокрутки)
Tofystedeth
@ retracile - да, вы делаете. Я не говорю «Вы должны игнорировать руководство», а скорее предполагаю, что в некоторых случаях руководство не обязательно существует во благо сообщества. Я не знал об ограничениях IDLE (опубликованных Tofystedeth), но в этом случае есть веский аргумент в пользу соблюдения соглашения.
ZombieSheep
13

Вы потеряли пробел, и вам, вероятно, нужен символ продолжения строки, т.е. а \.

s = "this is my really, really, really, really, really, really" +  \
    " really long string that I'd like to shorten."

или даже:

s = "this is my really, really, really, really, really, really"  \
    " really long string that I'd like to shorten."

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

s = ("this is my really, really, really, really, really, really"
    " really long string that I'd like to shorten.")

против:

s = ("this is my really, really, really, really, really, really",
    " really long string that I'd like to shorten.")

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

retracile
источник
2

Backslash:

s = "this is my really, really, really, really, really, really" +  \
    "really long string that I'd like to shorten."

или завернуть в паренс:

s = ("this is my really, really, really, really, really, really" + 
    "really long string that I'd like to shorten.")
рекурсивный
источник
2
Обратите внимание, что плюс необходим. Python объединяет строковые литералы, которые следуют друг за другом.
Букзор
2

Все это отличные ответы, но я не смог найти плагин редактора, который бы помог мне с редактированием «неявно сцепленных» строк, поэтому я написал пакет, чтобы мне было проще.

На pip (установите параграфы), если кто-то блуждает по этой старой теме, хотел бы проверить это. Форматирует многострочные строки так, как это делает html (сжимает пробел, две строки для нового абзаца, не заботясь о пробелах между строками).

from paragraphs import par


class SuddenDeathError(Exception):
    def __init__(self, cause: str) -> None:
        self.cause = cause

    def __str__(self):
        return par(
            f""" Y - e - e - e - es, Lord love you! Why should she die of
            {self.cause}? She come through diphtheria right enough the year
            before. I saw her with my own eyes. Fairly blue with it, she
            was. They all thought she was dead; but my father he kept ladling
            gin down her throat till she came to so sudden that she bit the bowl
            off the spoon. 

            What call would a woman with that strength in her have to die of
            {self.cause}? What become of her new straw hat that should have
            come to me? Somebody pinched it; and what I say is, them as pinched
            it done her in."""
        )


raise SuddenDeathError("influenza")

становится ...

__main__.SuddenDeathError: Y - e - e - e - es, Lord love you! Why should she die of influenza? She come through diphtheria right enough the year before. I saw her with my own eyes. Fairly blue with it, she was. They all thought she was dead; but my father he kept ladling gin down her throat till she came to so sudden that she bit the bowl off the spoon.

What call would a woman with that strength in her have to die of influenza? What become of her new straw hat that should have come to me? Somebody pinched it; and what I say is, them as pinched it done her in.

Все легко выстраивается с (Vim) 'gq'

фаэтон
источник
0

С помощью \вы можете расширить операторы до нескольких строк:

s = "this is my really, really, really, really, really, really" + \
"really long string that I'd like to shorten."

должно сработать.

Ikke
источник
0

Я склонен использовать несколько методов, не упомянутых здесь, для указания больших строк, но это для очень специфических сценариев. YMMV ...

  • Многострочные фрагменты текста, часто с отформатированными токенами (не совсем то, что вы просили, но все же полезно):

    error_message = '''
    I generally like to see how my helpful, sometimes multi-line error
    messages will look against the left border.
    '''.strip()
  • Выращивайте переменную по частям с помощью любого метода интерполяции строк, который вы предпочитаете:

    var = 'This is the start of a very,'
    var = f'{var} very long string which could'
    var = f'{var} contain a ridiculous number'
    var = f'{var} of words.'
  • Прочитайте это из файла. PEP-8 не ограничивает длину строк в файле; только строки вашего кода. :)

  • Используйте brute-force или ваш редактор, чтобы разбить строку на управляемые строки, используя новые строки, а затем удалите все новые строки. (Аналогично первой технике, которую я перечислил):

    foo = '''
    agreatbigstringthatyoudonotwanttohaveanyne
    wlinesinbutforsomereasonyouneedtospecifyit
    verbatimintheactualcodejustlikethis
    '''.replace('\n', '')
Larold
источник
0

Доступные Варианты:

  • обратная косая черта :"foo" \ "bar"
  • знак плюс с последующим обратным слешем :"foo" + \ "bar"
  • скобки :
    • ("foo" "bar")
    • скобки со знаком плюс :("foo" + "bar")
    • PEP8, E502: обратный слеш избыточен между скобками

Избегайте

Избегайте скобок с запятой: ("foo", "bar")которая определяет кортеж.


>>> s = "a" \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = "a" + \
... "b"
>>> s
'ab'
>>> type(s)
<class 'str'>
>>> s = ("a"
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> s = ("a",
... "b")
>>> type(s)
<class 'tuple'>
>>> s = ("a" + 
... "b")
>>> type(s)
<class 'str'>
>>> print(s)
ab
>>> 
marcanuy
источник
0

Если вы должны вставить длинный строковый литерал и хотите, чтобы flake8 закрывался, вы можете использовать его директивы закрывания . Например, в процедуре тестирования я определил некоторые ложные входные данные CSV. Я обнаружил, что разделение его на несколько строк, которые содержат строки, может быть очень запутанным, поэтому я решил добавить # noqa: E501следующее:

csv_test_content = """"STATION","DATE","SOURCE","LATITUDE","LONGITUDE","ELEVATION","NAME","REPORT_TYPE","CALL_SIGN","QUALITY_CONTROL","WND","CIG","VIS","TMP","DEW","SLP","AA1","AA2","AY1","AY2","GF1","MW1","REM"
"94733099999","2019-01-03T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","050,1,N,0010,1","22000,1,9,N","025000,1,9,9","+0260,1","+0210,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1","01,99,1,99,9,99,9,99999,9,99,9,99,9","01,1","SYN05294733 11/75 10502 10260 20210 60004 70100 333 70000="
"94733099999","2019-01-04T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","090,1,N,0021,1","22000,1,9,N","025000,1,9,9","+0378,1","+0172,1","99999,9","06,0000,9,1",,"0,1,02,1","0,1,02,1","03,99,1,99,9,99,9,99999,9,99,9,99,9","03,1","SYN04294733 11/75 30904 10378 20172 60001 70300="
"94733099999","2019-01-04T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","290,1,N,0057,1","99999,9,9,N","020000,1,9,9","+0339,1","+0201,1","99999,9","24,0000,9,1",,"0,1,02,1","0,1,02,1",,"02,1","SYN05294733 11970 02911 10339 20201 60004 70200 333 70000="
"94733099999","2019-01-05T22:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","200,1,N,0026,1","99999,9,9,N","000100,1,9,9","+0209,1","+0193,1","99999,9","24,0004,3,1",,"1,1,02,1","1,1,02,1","08,99,1,99,9,99,9,99999,9,99,9,99,9","51,1","SYN05294733 11/01 82005 10209 20193 69944 75111 333 70004="
"94733099999","2019-01-08T04:00:00","4","-32.5833333","151.1666666","45.0","SINGLETON STP, AS","FM-12","99999","V020","070,1,N,0026,1","22000,1,9,N","025000,1,9,9","+0344,1","+0213,1","99999,9","06,0000,9,1",,"2,1,02,1","2,1,02,1","04,99,1,99,9,99,9,99999,9,99,9,99,9","02,1","SYN04294733 11/75 40705 10344 20213 60001 70222="
"""  # noqa: E501
Геррит
источник
-1

Я использовал textwrap.dedent в прошлом. Это немного громоздко, поэтому я предпочитаю продолжения строки сейчас, но если вы действительно хотите отступ блока, я думаю, что это здорово.

Пример кода (где обрезка избавляет от первого '\ n' срезом):

import textwrap as tw
x = """\
       This is a yet another test.
       This is only a test"""
print(tw.dedent(x))

Объяснение:

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

Этот метод имеет ограничения в том, что очень длинные строки могут быть длиннее, чем вы хотите, в этом случае другие методы, которые объединяют строки, являются более подходящими.

MrMas
источник
1
Вместо того, чтобы обрезать, x[1:]вы можете поставить обратную косую черту после, x = """чтобы избежать первой новой строки.
Майкл Данн