Pythonic способ создания длинной многострочной строки

У меня очень длинный запрос. Я хотел бы разбить его на несколько строк в Python. Способ сделать это в JavaScript будет использовать несколько предложений и присоединиться к ним с оператором + (я знаю, может быть, это не самый эффективный способ сделать это, но я не очень обеспокоен производительностью на этом этапе, просто читаемость кода). Пример:

var long_string = 'some text not important. just garbage to' +
                  'illustrate my example';

Я попытался сделать что-то подобное в Python, но это не сработало, поэтому я использовал \ для разделения длинной строки. Тем не менее, я не уверен, что это единственный/лучший/pythonicest способ сделать это. Это выглядит неудобно. Фактический код:

query = 'SELECT action.descr as "action", '\
    'role.id as role_id,'\
    'role.descr as role'\
    'FROM '\
    'public.role_action_def,'\
    'public.role,'\
    'public.record_def, '\
    'public.action'\
    'WHERE role.id = role_action_def.role_id AND'\
    'record_def.id = role_action_def.def_id AND'\
    'action.id = role_action_def.action_id AND'\
    'role_action_def.account_id = ' + account_id + ' AND'\
    'record_def.account_id=' + account_id + ' AND'\
    'def_id=' + def_id

Ответ 1

Вы говорите о многострочных строках? Легко, используйте тройные кавычки, чтобы начать и завершить их.

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""

Вы можете использовать одинарные кавычки (3 из них, конечно, в начале и в конце) и обрабатывать результирующую строку s точно так же, как и любую другую строку.

ПРИМЕЧАНИЕ. Точно так же, как и в любой строке, что-либо между начальным и конечным кавычками становится частью строки, поэтому этот пример имеет ведущую заготовку (как указано @root45). Эта строка также будет содержать как пробелы, так и новые строки.

то есть,:.

' this is a very\n        long string if I had the\n        energy to type more and more ...'

Наконец, можно также построить длинные строки в Python следующим образом:

 s = ("this is a very"
      "long string too"
      "for sure ..."
     )

который будет не включать любые дополнительные пробелы или новые строки (это преднамеренный пример, показывающий, что приведет к эффекту пропуска пробелов):

'this is a verylong string toofor sure ...'

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

Ответ 2

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

query = ('SELECT   action.descr as "action", '
         'role.id as role_id,'
         'role.descr as role'
         ' FROM '
         'public.role_action_def,'
         'public.role,'
         'public.record_def, '
         'public.action'
         ' WHERE role.id = role_action_def.role_id AND'
         ' record_def.id = role_action_def.def_id AND'
         ' action.id = role_action_def.action_id AND'
         ' role_action_def.account_id = '+account_id+' AND'
         ' record_def.account_id='+account_id+' AND'
         ' def_id='+def_id)

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

Ответ 3

Разделительные линии \ работают для меня. Вот пример:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"

Ответ 4

Я был доволен этим:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')

Ответ 5

Я нахожу, что при построении длинных строк вы обычно делаете что-то вроде построения SQL-запроса, и в этом случае это лучше всего:

query = ' '.join((  # note double parens, join() takes an iterable
    "SELECT foo",
    "FROM bar",
    "WHERE baz",
))

Что Левон предложил, это хорошо, но может быть уязвим для ошибок:

query = (
    "SELECT foo"
    "FROM bar"
    "WHERE baz"
)

query == "SELECT fooFROM barWHERE baz"  # probably not what you want

Ответ 6

Вы также можете объединить переменные при использовании обозначения "":

foo = '1234'

long_string = """fosdl a sdlfklaskdf as
as df ajsdfj asdfa sld
a sdf alsdfl alsdfl """ +  foo + """ aks
asdkfkasdk fak"""

EDIT: Найден лучший способ с именованными параметрами и .format():

body = """
<html>
<head>
</head>
<body>
    <p>Lorem ipsum.</p>
    <dl>
        <dt>Asdf:</dt>     <dd><a href="{link}">{name}</a></dd>
    </dl>
    </body>
</html>
""".format(
    link='http://www.asdf.com',
    name='Asdf',
)

print(body)

Ответ 7

В Python >= 3.6 вы можете использовать Отформатированные строковые литералы (f строка)

query= f'''SELECT   action.descr as "action"
    role.id as role_id,
    role.descr as role
    FROM
    public.role_action_def,
    public.role,
    public.record_def,
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id = {account_id} AND
    def_id = {def_id}'''

Ответ 8

Этот подход использует:

  • только одна обратная косая черта, чтобы избежать начального перевода строки
  • почти нет внутренней пунктуации при использовании строки в тройных кавычках
  • удаляет локальные отступы с помощью модуля textwrap inspect
  • использует интерполяцию строк в формате Python 3.6 ('f') для переменных account_id и def_id.

Этот способ выглядит наиболее питонным для меня.

# import textwrap  # See update to answer below
import inspect

# query = textwrap.dedent(f'''\
query = inspect.cleandoc(f'''
    SELECT action.descr as "action", 
    role.id as role_id,
    role.descr as role
    FROM 
    public.role_action_def,
    public.role,
    public.record_def, 
    public.action
    WHERE role.id = role_action_def.role_id AND
    record_def.id = role_action_def.def_id AND
    action.id = role_action_def.action_id AND
    role_action_def.account_id = {account_id} AND
    record_def.account_id={account_id} AND
    def_id={def_id}'''
)

Обновление: 29.01.2009 Включение предложения @ShadowRanger для использования inspect.cleandoc вместо textwrap.dedent

Ответ 9

Например:

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1={} "
       "and condition2={}").format(1, 2)

Output: 'select field1, field2, field3, field4 from table 
         where condition1=1 and condition2=2'

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

sql = ("select field1, field2, field3, field4 "
       "from table "
       "where condition1='{0}' "
       "and condition2='{1}'").format('2016-10-12', '2017-10-12')

Output: "select field1, field2, field3, field4 from table where
         condition1='2016-10-12' and condition2='2017-10-12'"

Ответ 10

Я считаю textwrap.dedent лучшим для длинных строк, как описано здесь:

def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
    """)
    do_something(code_snippet)

Ответ 11

Лично я считаю, что лучшим (простым, безопасным и Pythonic) способом написания необработанных SQL-запросов на Python является следующий, особенно при использовании модуля Python sqlite3:

query = '''
    SELECT
        action.descr as action,
        role.id as role_id,
        role.descr as role
    FROM
        public.role_action_def,
        public.role,
        public.record_def,
        public.action
    WHERE
        role.id = role_action_def.role_id
        AND record_def.id = role_action_def.def_id
        AND action.id = role_action_def.action_id
        AND role_action_def.account_id = ?
        AND record_def.account_id = ?
        AND def_id = ?
'''
vars = (account_id, account_id, def_id)   # a tuple of query variables
cursor.execute(query, vars)   # using Python sqlite3 module

Pros

  • Аккуратный и простой код (Pythonic!)
  • Безопасно от SQL-инъекции
  • Совместим с Python 2 и Python 3 (это Pythonic в конце концов)
  • Конкатенация строк не требуется
  • Не нужно гарантировать, что самый правый символ каждой строки является пробелом

Cons

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

Ответ 12

Я обычно использую что-то вроде этого:

text = '''
    This string was typed to be a demo
    on how could we write a multi-line
    text in Python.
'''

Если вы хотите удалить надоедливые пробелы в каждой строке, вы можете сделать следующее:

text = '\n'.join(line.lstrip() for line in text.splitlines())

Ответ 13

Ваш фактический код не должен работать, вам не хватает пробелов в конце "строк" ​​(например: role.descr as roleFROM...)

Существует три раза для многострочной строки:

string = """line
  line2
  line3"""

Он будет содержать разрывы строк и дополнительные пробелы, но для SQL это не проблема.

Ответ 14

Вы также можете поместить sql-инструкцию в отдельный файл action.sql и загрузить его в файл py с помощью

with open('action.sql') as f:
   query = f.read()

Таким образом, sql-операторы будут отделены от кода python. Если в операторе sql есть параметры, которые необходимо заполнить из python, вы можете использовать форматирование строк (например,% s или {field})

Ответ 15

"À la" Scala (но я думаю, что это самый пифонический путь, который требует OQ):

description = """
            | The intention of this module is to provide a method to 
            | pass meta information in markdown_ header files for 
            | using it in jinja_ templates. 
            | 
            | Also, to provide a method to use markdown files as jinja 
            | templates. Maybe you prefer to see the code than 
            | to install it.""".replace('\n            | \n','\n').replace('            | ',' ')

Если вы хотите окончательную строку без линий перехода, просто поставьте \n в начале первого аргумента второй замены:

.replace('\n            | ',' ')`.

Примечание: белая линия между "... шаблонами". и "Кроме того..." требует пробела после |.

Ответ 16

Я использую рекурсивную функцию для создания сложных SQL-запросов. Этот метод обычно можно использовать для построения больших строк при сохранении читаемости кода.

# Utility function to recursively resolve SQL statements.
# CAUTION: Use this function carefully, Pass correct SQL parameters {},
# TODO: This should never happen but check for infinite loops
def resolveSQL(sql_seed, sqlparams):
    sql = sql_seed % (sqlparams)
    if sql == sql_seed:
        return ' '.join([x.strip() for x in sql.split()])
    else:
        return resolveSQL(sql, sqlparams)

P.S: Посмотрите на потрясающую библиотеку python-sqlparse, чтобы при необходимости печатать SQL-запросы. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

Ответ 17

Другой вариант, который, по моему мнению, более читабельен, когда код (например, переменная) имеет отступ, а выходная строка должна быть одним лайнером (без символов новой строки):

def some_method():

    long_string = """
a presumptuous long string 
which looks a bit nicer 
in a text editor when
written over multiple lines
""".strip('\n').replace('\n', ' ')

    return long_string 

Ответ 18

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

Прокомментируйте каждый фрагмент:

nursery_rhyme = (
    'Mary had a little lamb,'          # Comments are great!
    'its fleece was white as snow.'
    'And everywhere that Mary went,'
    'her sheep would surely go.'       # What a pesky sheep.
)

Комментарий не разрешен после продолжения:

При использовании продолжения строки с обратной косой чертой (\) комментарии не допускаются. Вы получите SyntaxError: unexpected character after line continuation character ошибки SyntaxError: unexpected character after line continuation character.

nursery_rhyme = 'Mary had a little lamb,' \  # These comments
    'its fleece was white as snow.'       \  # are invalid!
    'And everywhere that Mary went,'      \
    'her sheep would surely go.'
# => SyntaxError: unexpected character after line continuation character

Лучшие комментарии для строк Regex:

Основываясь на примере с https://docs.python.org/3/library/re.html#re.VERBOSE,

a = re.compile(
    r'\d+'  # the integral part
    r'\.'   # the decimal point
    r'\d*'  # some fractional digits
)
# Using VERBOSE flag, IDE usually can't syntax highight the string comment.
a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)

Ответ 19

Мне нравится этот подход, потому что он дает право на чтение. В тех случаях, когда у нас длинные струны, это невозможно! В зависимости от уровня отступа вы находитесь и до сих пор ограничены 80 символами в строке... Ну... Больше ничего не нужно говорить. На мой взгляд, руководства по питонскому стилю все еще очень расплывчаты. Я выбрал подход @Eero Aaltonen, потому что он дает преимущество в чтении и здравом смысле. Я понимаю, что руководства по стилю должны помочь нам, а не сделать нашу жизнь беспорядочной. Спасибо!

class ClassName():
    def method_name():
        if condition_0:
            if condition_1:
                if condition_2:
                    some_variable_0 =\
"""
some_js_func_call(
    undefined, 
    {
        'some_attr_0': 'value_0', 
        'some_attr_1': 'value_1', 
        'some_attr_2': '""" + some_variable_1 + """'
    }, 
    undefined, 
    undefined, 
    true
)
"""

Ответ 20

Эй, попробуйте что-то вроде этой надежды, это работает, как в этом формате, он вернет вам непрерывную линию, как вы успешно спросили об этом свойстве.

"message": f'you have successfully inquired about '
           f'{enquiring_property.title} Property owned by '
           f'{enquiring_property.client}'

Ответ 21

Обычно я использую list и join для многострочных комментариев/строк.

lines = list()
lines.append('SELECT action.enter code here descr as "action", ')
lines.append('role.id as role_id,')
lines.append('role.descr as role')
lines.append('FROM ')
lines.append('public.role_action_def,')
lines.append('public.role,')
lines.append('public.record_def, ')
lines.append('public.action')
query = " ".join(lines)

Вы можете использовать любую строку, чтобы присоединиться ко всему этому элементу списка, например ' \n ' (новая строка) или ' , ' (запятая) или ' '(пространство)

Ура.. !!