关于python: python创建长多行字符串的方法

Pythonic way to create a long multi-line string

我有一个很长的问题。我想用Python把它分成几行。在JavaScript中实现这一点的一种方法是使用几个句子并将它们与+操作符连接起来(我知道,这可能不是最有效的方法,但我并不真正关心这个阶段的性能,只关心代码的可读性)。例子:

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

我尝试在Python中做类似的事情,但是没有成功,所以我使用\来分割长字符串。然而,我不确定这是否是唯一的/最好的/最好的方法。它看起来很尴尬。实际的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
2
3
s =""" this is a very
        long string if I had the
        energy to type more and more ..."""

您也可以使用单引号(当然在开始和结束时可以使用其中的3个),并像对待任何其他字符串一样对待得到的字符串s

注意:就像任何字符串一样,开始和结束引号之间的任何内容都是字符串的一部分,所以这个示例有一个前导空格(@root45指出了这一点)。该字符串还将包含空白和换行。

例如,:

1
2
3
' this is a very
        long string if I had the
        energy to type more and more ...'

最后,还可以用Python像这样构造长行:

1
2
3
4
 s = ("this is a very"
     "long string too"
     "for sure ..."
     )

这将不包括任何额外的空格或换行(这是一个故意的例子,显示了跳过空格的效果):

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

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


如果你不想要多行字符串,而只想要一个长单行字符串,你可以使用圆括号,只要确保字符串段之间不包含逗号,那么它就是一个元组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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语句中,多行字符串也可以。但是,如果多行字符串中包含的额外空格有问题,那么这将是实现您想要的效果的好方法。


\的换行对我很有用。举个例子:

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


我发现自己对这个很满意:

1
2
3
4
5
6
string ="""This is a
very long string,
containing commas,
that I split up
for readability"""
.replace('
'
,' ')


我发现,当构建长字符串时,您通常在做类似于构建SQL查询的事情,在这种情况下,这是最好的:

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

Levon的建议很好,但可能容易出错:

1
2
3
4
5
6
7
query = (
   "SELECT foo"
   "FROM bar"
   "WHERE baz"
)

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


你也可以连接变量时,使用""符号:

1
2
3
4
5
6
foo = '1234'

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

EDIT:找到一个更好的方法,使用名为params和.format():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
body ="""
<html>
<head>
</head>
<body>
    <p>
Lorem ipsum.
</p>
    <dl>
        <dt>Asdf:</dt>     <dd>{name}</dd>
    </dl>
    </body>
</html>
"""
.format(
    link='http://www.asdf.com',
    name='Asdf',
)

print(body)


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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}'''


这种方法使用:

只有一个反斜杠来避免初始换行符使用三重引号的字符串几乎没有内部标点符号使用textwrap inspect模块去除局部缩进对account_iddef_id变量使用python 3.6格式的字符串插值('f')。

在我看来,这种方式最像蟒蛇。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 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}'''

)

更新:1/29/2019采纳@ShadowRanger使用inspect.cleandoc代替textwrap.dedent的建议


例如:

1
2
3
4
5
6
7
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'

如果条件的值应该是字符串,您可以这样做:

1
2
3
4
5
6
7
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'"


我发现textwrap.dedent最适合长字符串,如下所述:

1
2
3
4
5
6
7
def create_snippet():
    code_snippet = textwrap.dedent("""\
        int main(int argc, char* argv[]) {
            return 0;
        }
   """
)
    do_something(code_snippet)

我个人认为以下是用Python编写原始SQL查询的最佳方法(简单、安全、符合Python风格),特别是在使用Python的sqlite3模块时:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

优点

简洁而简单的代码(python的!)避免SQL注入兼容Python 2和Python 3(毕竟它是Python风格的)不需要字符串连接不需要确保每一行最右边的字符都是空格

缺点

由于查询中的变量被?占位符替换,所以当查询中有很多变量时,跟踪哪个?将被哪个Python变量替换可能会变得有点困难。


我通常这样用:

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

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

1
2
text = '
'
.join(line.lstrip() for line in text.splitlines())


您实际的代码不应该工作,您丢失了"行"末尾的空格(例如:role.descr as roleFROM...)

多行字符串有三重引号:

1
2
3
string ="""line
  line2
  line3"""

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


"ala"Scala方式(但我认为是OQ要求的最python化的方式):

1
2
3
4
5
6
7
8
9
10
11
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('
            |
'
,'
'
).replace('            | ',' ')

如果你想要没有跳线的final str,只需在第二个replace的第一个参数的开头加上
:

1
2
.replace('
            | '
,' ')`.

注意:"…templates."和"Also,…"之间的白线需要|后面的空格。


您还可以将sql语句放在一个单独的文件action.sql中,并将其加载到py文件中

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

因此sql语句将从python代码中分离出来。如果sql语句中有需要用python填充的参数,可以使用字符串形式(如%s或{field})


我使用递归函数来构建复杂的SQL查询。这种技术通常可用于构建大型字符串,同时保持代码的可读性。

1
2
3
4
5
6
7
8
9
# 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


另一个选项,我认为当代码(e。g变量)缩进,输出字符串应该是一行(没有换行):

1
2
3
4
5
6
7
8
9
10
11
12
def some_method():

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

    return long_string

我喜欢这种方法,因为它赋予阅读特权。在我们有长字符串的情况下是没有办法的!取决于缩进的级别,你仍然被限制在每行80个字符…嗯…不用再说什么了。在我看来,python风格指南仍然非常模糊。我采用@Eero Aaltonen方法,因为它赋予阅读和常识以特权。我明白,风格指南应该帮助我们,而不是让我们的生活一团糟。谢谢!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
)
"""

通常,对于多行注释/字符串,我使用listjoin

1
2
3
4
5
6
7
8
9
10
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)

您可以使用任何字符串来连接所有列表元素,比如"
"(换行)或","(逗号)或""(空格)

干杯! !