Pythonic方式创建一个长多行字符串

Pab*_*her 1160 python string multiline multilinestring

我有一个很长的查询.我想在Python中将它分成几行.在JavaScript中实现它的一种方法是使用几个句子并将它们与+运算符连接(我知道,也许这不是最有效的方法,但我并不关心这个阶段的性能,只是代码可读性) .例:

var long_string = 'some text not important. just garbage to' +
                  'illustrate my example';
Run Code Online (Sandbox Code Playgroud)

我尝试在Python中做类似的事情,但它不起作用,所以我习惯\拆分长字符串.但是,我不确定这是否是唯一/最好/最好的方式.看起来很尴尬.实际代码:

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
Run Code Online (Sandbox Code Playgroud)

Lev*_*von 1994

你在谈论多线字符串吗?轻松,使用三重引号来开始和结束它们.

s = """ this is a very
        long string if I had the
        energy to type more and more ..."""
Run Code Online (Sandbox Code Playgroud)

您也可以使用单引号(当然在开始和结束时使用其中3个)并将结果字符串视为s任何其他字符串.

注意:就像任何字符串一样,起始引号和结束引号之间的任何内容都成为字符串的一部分,因此该示例有一个前导空格(由@ root45指出).该字符串还包含空格和换行符.

IE中:

' this is a very\n        long string if I had the\n        energy to type more and more ...'
Run Code Online (Sandbox Code Playgroud)

最后,还可以在Python中构造长行,如下所示:

 s = ("this is a very"
      "long string too"
      "for sure ..."
     )
Run Code Online (Sandbox Code Playgroud)

这将包括任何额外的空格或换行符(这是一个故意的例子,显示跳过空格会产生什么效果):

'this is a verylong string toofor sure ...'
Run Code Online (Sandbox Code Playgroud)

不需要逗号,只需将要连接在一起的字符串放入一对括号中,并确保考虑任何所需的空格和换行符.

  • @LucasMalor相邻的字符串是编译时串联.不使用`+`运算符使连接在运行时发生? (34认同)
  • 作为参考,以下是此现象的官方文档:https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation(python 2)和https://docs.python.org/ 3/reference/lexical_analysis.html#string-literal-concatenation(python 3) (11认同)
  • 对于方法2和unicode字符串:您只需要将第一个字符串标记为unicode,即u'a'\n'b'\n'c'=> u'abc'. (8认同)
  • 我更喜欢明确地使用"+"运算符作为第二种方法.没那么麻烦,提高了可读性. (8认同)
  • 您的示例很好,但是我希望它包括演示如何安全可靠地将变量数据嵌入查询中。OP和@jessee示例代码都显示了如何不正确地进行操作(它们是对SQL攻击的邀请)。另请参见:https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html (3认同)
  • 您可以使用`textwrap.dedent`删除不需要的前导空格。https://docs.python.org/3/library/textwrap.html#textwrap.dedent (2认同)

Jes*_*sse 167

如果您不想要多行字符串但只需要一个长单行字符串,则可以使用括号,只要确保字符串段之间不包含逗号,那么它将是一个元组.

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)
Run Code Online (Sandbox Code Playgroud)

在像你正在构建的SQL语句中,多行字符串也可以.但是如果多行字符串包含的额外空格会有问题,那么这将是实现您想要的好方法.

  • 这个例子是SQL注入攻击的一扇门.请不要在任何面向公众的应用程序中使用它.有关如何使用"占位符"的信息,请参阅MySQL文档:https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html (33认同)
  • 格式化这个字符串的另一种方法是在右括号后添加`.format(...)`.`%`格式化表示法也必须有效,但我还没有尝试过 (3认同)
  • 请注意,每一行必须以字符串常量结束,因此`'foo'+ variable`将不起作用,但`'foo'+ variable +''`将会起作用. (3认同)
  • @200OK你的意思是在“”之后? (2认同)

amp*_*ent 130

\为我打破工作线.这是一个例子:

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"
Run Code Online (Sandbox Code Playgroud)

  • 我强烈建议将空格放在以下行的开头而不是后面行的结尾处.这种方式意外丢失的方式更明显(因此不太可能发生). (14认同)
  • 我更喜欢三重引号表示法或将内部()包装到\字符 (9认同)
  • [PEP 8](https://peps.python.org/pep-0008/#maximum-line-length) 和 [Black](https://black.readthedocs.io/en/stable/contributing/reference/ Reference_functions.html#black.linegen.normalize_prefix) 不鼓励使用反斜杠来继续行。 (3认同)
  • @Alfe 不用再担心丢失了。VScode 错过一个就会心脏病发作 (2认同)

Eer*_*nen 48

我发现自己对这个感到满意:

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

  • 不同意.如果第一行("string = ...")严重缩进怎么办?人们不得不将以下几行去除零压痕,这在缩进块的中间看起来很丑. (23认同)
  • 如果您关心代码折叠,这会在大多数编辑器中破坏它。 (3认同)
  • 好吧,我的大部分长字符串都发生在模块级别,这非常适合。就您而言,这显然不是最好的解决方案。 (2认同)

dar*_*ine 36

我发现在构建长字符串时,通常会执行类似构建SQL查询的操作,在这种情况下,这是最好的:

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

Levon建议什么是好的,但可能容易受到错误的影响:

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

query == "SELECT fooFROM barWHERE baz"  # probably not what you want
Run Code Online (Sandbox Code Playgroud)

  • +1减轻代码审查员不必刻意检查每行的右端**空间不足**.正如@KarolyHorvath所指出的那样,OP多次犯了这个错误. (6认同)
  • @ BobStein-VisiBone代码评论不应该是关于语法错误或像这样的小错误,它们应该是关于实质的.如果某人正在为具有语法错误的审查放置代码(因此根本不会运行或在某些情况下运行)那么就会出现严重错误.在提交之前运行lint并不难.如果这个人没有注意到他们的程序运行不正确,因为他们犯了这么明显的错误,他们就不应该犯错了. (3认同)
  • 当检查以类似方式编码的多行字符串时,我要求每行的* left *末尾有足够的空格,以便于确认。 (2认同)

Ste*_*ica 31

PEP 8 风格指南建议使用括号:

换行长行的首选方法是在圆括号、方括号和大括号内使用 Python 的隐式续行。通过将表达式括在括号中,可以将长行分成多行。应优先使用这些内容而不是使用反斜杠来继续行。

例子:

long_string = (
    "This is a lengthy string that takes up a lot of space. I am going to "
    "keep on typing words to fill up more and more space to show how you can "
    "split the string across multiple lines."
)
Run Code Online (Sandbox Code Playgroud)


gjg*_*jgj 28

您还可以在使用""符号时连接变量:

foo = '1234'

long_string = """fosdl a sdlfklaskdf as
as df ajsdfj asdfa sld
a sdf alsdfl alsdfl """ +  foo + """ aks
asdkfkasdk fak"""
Run Code Online (Sandbox Code Playgroud)

编辑:找到一个更好的方法,使用命名参数和.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)
Run Code Online (Sandbox Code Playgroud)

  • 这里使用 [f strings](/sf/answers/3552263361/) 似乎更自然和简单。 (2认同)

Chr*_*uns 23

这种方法使用:

  • 只需一个反斜杠即可避免初始换行
  • 使用三引号字符串几乎没有内部标点符号
  • 使用textwrap inspect模块剥离局部缩进
  • 使用python 3.6格式化字符串插值('f')account_iddef_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}'''
)
Run Code Online (Sandbox Code Playgroud)

更新:1/29/2019合并@ ShadowRanger的建议使用inspect.cleandoc而不是textwrap.dedent

  • 虽然它看起来确实不错,但我认为这种方法很容易受到 SQL 注入的攻击。遗憾的是 f 字符串不适合 SQL 查询。从其他评论来看,最好使用 `cursor.execute` 代替 https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html (6认同)
  • 注意:[inspect.cleandoc`比`textwrap.dedent`更好一点(https://docs.python.org/3/library/inspect.html#inspect.cleandoc),因为它不需要第一个line为空,结尾处有换行符。 (4认同)
  • @ShadowRanger哇,我以前从未使用过cleandoc。我更新了答案,将来会使用`inspect.cleandoc`来实现。 (2认同)

Vla*_*den 22

在Python> = 3.6中,您可以使用格式化字符串文字(f string)

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}'''
Run Code Online (Sandbox Code Playgroud)

  • 仍然容易受到SQL注入的攻击 (5认同)
  • 如果我想记录多行字符串的结果并且没有显示左侧选项卡/空格,那么f字符串将如何工作? (4认同)

pan*_*ang 16

例如:

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'
Run Code Online (Sandbox Code Playgroud)

如果condition的值应该是一个字符串,你可以这样做:

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'"
Run Code Online (Sandbox Code Playgroud)


use*_*855 16

添加到@Levon的答案......

1. 创建一个多行字符串,如下所示:

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

print(paragraph)
Run Code Online (Sandbox Code Playgroud)

输出:

'this is a very\n        long string if I had the\n        energy to type more and more ...'
Run Code Online (Sandbox Code Playgroud)

该字符串将包含换行符和空格。所以删除它们。

2.使用正则表达式删除多余的空格

paragraph = re.sub('\s+', ' ', paragraph)
print(paragraph)
Run Code Online (Sandbox Code Playgroud)

输出:

'this is a very long string if I had the energy to type more and more ...'
Run Code Online (Sandbox Code Playgroud)


Fah*_*mad 10

我个人发现以下是在Python中编写原始SQL查询的最佳(简单,安全和Pythonic)方法,尤其是在使用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's sqlite3 module
Run Code Online (Sandbox Code Playgroud)

优点

  • 整洁简单的代码(Pythonic!)
  • 从SQL注入安全
  • 兼容Python 2和Python 3(毕竟它是Pythonic)
  • 不需要字符串连接
  • 无需确保每行的最右侧字符是空格

缺点

  • 由于查询中的变量被?占位符替换,因此?当查询中存在大量Python变量时,跟踪哪个Python变量可能会变得有点困难.

  • @Ben如果执行`cursor.execute(query.format(vars))`,您将不再能从准备好的语句中获利,因此您很容易遇到许多类型的问题,首先要注意的是,如果参数不仅仅是数字,则需要在SQL查询中双引号。 (2认同)

小智 10

作为在 Python 中处理长字符串的一般方法,您可以使用三重引号,split并且join

_str = ' '.join('''Lorem ipsum dolor sit amet, consectetur adipiscing
        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 ex ea commodo.'''.split())
Run Code Online (Sandbox Code Playgroud)

输出:

'Lorem ipsum dolor sit amet, consectetur adipiscing 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 ex ea commodo.'
Run Code Online (Sandbox Code Playgroud)

关于 OP 与 SQL 查询相关的问题,下面的答案忽略了这种构建 SQL 查询的方法的正确性,只关注以可读和美观的方式构建长字符串,而无需额外导入。它还忽略了这带来的计算负载。

使用三重引号,我们构建了一个长且可读的字符串,然后我们将其分解为一个列表,split()从而去除空白,然后用' '.join(). 最后,我们使用以下format()命令插入变量:

'Lorem ipsum dolor sit amet, consectetur adipiscing 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 ex ea commodo.'
Run Code Online (Sandbox Code Playgroud)

产生:

account_id = 123
def_id = 321

_str = '''
    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 = {}
    '''

query = ' '.join(_str.split()).format(account_id, account_id, def_id)

Run Code Online (Sandbox Code Playgroud)

这种方法不符合PEP 8,但我发现它有时很有用。

请注意,原始字符串中的大括号由 format() 函数使用。


fre*_*rik 9

我觉得textwrap.dedent最好的长字符串描述在这里:

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

  • 我喜欢防止自动换行的黑色斜线,非常感谢! (2认同)
  • 如果您使用“inspect.cleandoc”而不是“textwrap.dedent”,则不需要反斜杠。 (2认同)
  • 这是严重低估的。 (2认同)

小智 7

其他人已经提到了括号方法,但是我想在括号中添加,允许内联注释。

评论每个片段:

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.
)
Run Code Online (Sandbox Code Playgroud)

继续后不允许发表评论:

当使用反斜杠连续行(\)时,不允许注释。您会收到一个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
Run Code Online (Sandbox Code Playgroud)

对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
)
Run Code Online (Sandbox Code Playgroud)
# 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)
Run Code Online (Sandbox Code Playgroud)


小智 6

我通常使用这样的东西:

text = '''
    This string was typed to be a demo
    on how could we write a multi-line
    text in Python.
'''
Run Code Online (Sandbox Code Playgroud)

如果你想删除每行中烦人的空格,你可以这样做:

text = '\n'.join(line.lstrip() for line in text.splitlines())
Run Code Online (Sandbox Code Playgroud)

  • 查看Python的[`textwrap.dedent`](https://github.com/python/cpython/blob/master/Lib/textwrap.py#L414)函数,它位于标准库中,它具有您需要的功能。 (2认同)

Ric*_*ick 6

嗯。

我知道这个问题发布已经很长时间了。但我刚刚找到了我想要用来将长多行字符串分配给项目中的变量的样式。这需要一些额外的运行时间,但仍然保留了代码的美观,即使我分配字符串的变量是大量缩进的。

    # Suppose the following code is heavily indented
    line3header = "Third"

    variable = fr"""

First line.
Second line.
{line3header} line.
{{}} line.
...
The last line.

    """.strip()
    """A variable whose name is Variable.

    You can even add a docstring here.
    """

    variable = variable.format("Fourth")
    print(variable)
    variable += "\n"
    print(variable, end="")
Run Code Online (Sandbox Code Playgroud)

就这样。


Kar*_*ath 5

你的实际代码不应该工作;您在“行”的末尾缺少空格(例如,role.descr as roleFROM...)。

多行字符串有三重引号:

string = """line
  line2
  line3"""
Run Code Online (Sandbox Code Playgroud)

它将包含换行符和额外的空格,但对于 SQL 这不是问题。


小智 5

尝试这样的事情。就像这种格式一样,它将返回一条连续的行,就像您已成功查询此属性一样:

"message": f'You have successfully inquired about '
           f'{enquiring_property.title} Property owned by '
           f'{enquiring_property.client}'
Run Code Online (Sandbox Code Playgroud)


Flo*_*low 5

tl;dr:使用"""\"""包裹字符串,如

string = """\
This is a long string
spanning multiple lines.
"""
Run Code Online (Sandbox Code Playgroud)

来自官方 Python 文档

字符串文字可以跨越多行。一种方法是使用三引号:"""...""" 或 '''...'''。行尾会自动包含在字符串中,但可以通过在行尾添加 \ 来防止出现这种情况。下面的例子:

print("""\
Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
""")
Run Code Online (Sandbox Code Playgroud)

产生以下输出(注意不包括初始换行符):

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
Run Code Online (Sandbox Code Playgroud)


e.d*_*n.a 5

结合以下想法:

莱文杰西,法希尔德德斯科特

根据我的格式建议,您可以将查询编写为:

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
         )

 vars = (account_id, account_id, def_id)     # A tuple of the query variables
 cursor.execute(query, vars)                 # Using Python's sqlite3 module
Run Code Online (Sandbox Code Playgroud)

或者像:

vars = []
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 = '
                 vars.append(account_id) or '?'
             ' AND'
             ' record_def.account_id = '
                 vars.append(account_id) or '?'
             ' AND'
             ' def_id = '
                 vars.append(def_id) or '?'
         )

 cursor.execute(query, tuple(vars))  # Using Python's sqlite3 module
Run Code Online (Sandbox Code Playgroud)

与 'IN' 和 'vars.extend(options) 或 n_options(len(options))' 一起使用可能会很有趣,其中:

def n_options(count):
    return '(' + ','.join(count*'?') + ')'
Run Code Online (Sandbox Code Playgroud)

或者根据darkfeline的提示,您可能仍然会在使用那些前导空格和分隔符以及命名占位符时犯错误:

SPACE_SEP = ' '
COMMA_SEP = ', '
AND_SEP   = ' AND '

query = SPACE_SEP.join((
    'SELECT',
        COMMA_SEP.join((
        'action.descr as "action"',
        'role.id as role_id',
        'role.descr as role',
        )),
    'FROM',
        COMMA_SEP.join((
        'public.role_action_def',
        'public.role',
        'public.record_def',
        'public.action',
        )),
    'WHERE',
        AND_SEP.join((
        'role.id = role_action_def.role_id',
        'record_def.id = role_action_def.def_id',
        'action.id = role_action_def.action_id',
        'role_action_def.account_id = :account_id',
        'record_def.account_id = :account_id',
        'def_id = :def_id',
        )),
    ))

vars = {'account_id':account_id,'def_id':def_id}  # A dictionary of the query variables
cursor.execute(query, vars)                       # Using Python's sqlite3 module
Run Code Online (Sandbox Code Playgroud)

请参阅Cursor.execute-function 的文档

“这是[最Pythonic]的方式!” - ...


归档时间:

查看次数:

1022032 次

最近记录:

6 年,1 月 前