web-dev-qa-db-ja.com

長い複数行の文字列を作成するためのPythonicの方法

非常に長い問い合わせがあります。私はそれをPythonのいくつかの行に分けたいと思います。 JavaScriptでそれを行うには、いくつかの文を使用し、それらを+演算子で結合します(私は知っていますが、これを実行するのが最も効率的な方法ではありません)例:

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

私はPythonで似たようなことをやろうとしたが、うまくいかなかったので、長い文字列を分割するために\を使った。しかし、これが唯一の/ best/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
1006
Pablo Mescher

あなたは複数行の文字列について話していますか?簡単に、それらを開始および終了するために三重引用符を使用してください。

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

あなたは一重引用符を使うこともでき(もちろんそれらのうちの3つは始めと終わりに)、結果の文字列sを他の文字列と同じように扱うことができます。

_ note _ :他の文字列と同様に、開始引用符と終了引用符の間にあるものはすべて文字列の一部になります。この文字列には空白と改行の両方も含まれます。

すなわち、

' 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 ..."
     )

not は余分な空白や改行を含みます(これは空白をスキップした場合の結果を示す慎重な例です)。

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

カンマは必要ありません。結合する文字列を括弧で囲み、必要な空白と改行を必ず考慮してください。

1732
Levon

複数行の文字列が不要で、長い単一行の文字列が必要な場合は、括弧を使用できます。文字列セグメントの間にカンマを含めないようにしてください。それがTupleになります。

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文では、複数行の文字列も問題ないでしょう。しかし、複数行の文字列に含まれる余分な空白が問題になる場合は、これがあなたが望むことを達成するための良い方法になるでしょう。

151
Jesse

\による改行は私のために働きます。これが一例です。

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

私はこれに満足しています。

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

長い文字列を作成するときは、通常、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
34
darkfeline

また、 ""記法を使うときに変数を連結することもできます:

foo = '1234'

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

編集:名前付きのパラメータと.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)
25
gjgjgj

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}'''
19
Vlad Bezden

このアプローチは以下を使用します。

  • 最初の改行を避けるためにバックスラッシュを1つだけ
  • 三重引用符付き文字列を使用しても句読点はほとんど使用されない
  • を使用してローカルのインデントを削除します テキストの折り返し inspectモジュール
  • account_iddef_id変数にはPython 3.6フォーマットの文字列補間( 'f')を使います。

この方法は私にとって最もPythonicに見えます。

# 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 inspect.cleandocの代わりにtextwrap.dedentを使用するという@ ShadowRangerの提案を取り入れる

14

例えば:

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'

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'"
11
pangpang

textwrap.dedent が長い文字列に最適であることがわかります ここ

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

私は個人的には、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

長所

  • きちんとした簡単なコード(Pythonic!)
  • SQLインジェクションから安全
  • Python 2とPython 3の両方と互換性があります(結局Pythonicです)。
  • 文字列の連結は不要
  • 各行の右端の文字がスペースであることを確認する必要はありません

短所

  • クエリ内の変数は?プレースホルダに置き換えられるため、クエリ内に変数がたくさんある場合、どの?をどのPython変数に置き換えるのかを追跡するのが少し困難になる場合があります。
7
Faheel Ahmad

私は通常このようなものを使います:

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())
3

実際のコードは機能しないはずです。 "lines"の末尾に空白がありません(例:role.descr as roleFROM...

複数行の文字列には3つの引用符があります。

string = """line
  line2
  line3"""

改行や余分なスペースが含まれますが、SQLの場合は問題ありません。

3
Karoly Horvath

Sql-statementを別のファイルaction.sqlに置き、それをpyファイルにロードすることもできます。

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

そのため、SQL文はPythonコードから分離されます。 sqlステートメントにpythonから入力する必要があるパラメータがある場合は、文字列フォーマット(%sや{field}など)を使用できます。

2
mrijken

"àla" Scala way(ただし、OQが要求する最もPythonicな方法だと思います):

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('            | ',' ')

ジャンプ行のない最後のstrが必要な場合は、2番目の置換の最初の引数の先頭に\nを付けてください。

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

注: "...テンプレート"の間の白い線。そして "また、..."は|の後に空白を必要とします。

2
victe

再帰関数を使って複雑な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:必要に応じてSQLクエリをきれいに印刷するための素晴らしいpython-sqlparseライブラリを見てください。 http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

1
Sandeep

コード(変数など)がインデントされていて、出力文字列が1行になっている(改行がない)場合は、もう少し読みやすくなると思います。

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 
1
Eyal Levin

tl; dr:"""\および"""を使用して、文字列をラップします

string = """\
This is a long string
spanning multiple lines.
"""

公式pythonドキュメント から:

文字列リテラルは複数行にまたがることができます。 1つの方法は、トリプルクォートを使用することです: "" "..." ""または '' '...' ''。行末は自動的に文字列に含まれますが、行末に\を追加することでこれを防ぐことができます。次の例:

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

次の出力を生成します(最初の改行は含まれないことに注意してください)。

Usage: thingy [OPTIONS]
     -h                        Display this usage message
     -H hostname               Hostname to connect to
0
Flow

公式pythonドキュメント から:

文字列リテラルは複数行にまたがることができます。 1つの方法は、トリプルクォートを使用することです: "" "..." ""または '' '...' ''。行末は自動的に文字列に含まれますが、行末に\を追加することでこれを防ぐことができます。次の例:

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

次の出力を生成します(最初の改行は含まれないことに注意してください)。

0
Flow

他の人はすでに括弧の方法について言及しました、しかし私は括弧でそれを加えたいです、インラインコメントは許されます。

各断片についてコメントする:

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エラーが発生します。

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

正規表現文字列に対するより良いコメント:

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)
0
ddrscott

この形式の場合、このプロパティについての問い合わせに成功したように、連続した行が返されるように、このようなものを試してみてください `

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

それが読む特権を持っているので、私はこのアプローチが好きです。長い文字列がある場合は方法がありません。あなたが行っているインデントのレベルにもよりますが、それでも1行につき80文字に制限されます。私の見解では、Pythonスタイルのガイドはまだ非常に曖昧です。私は@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
)
"""
0
Eduardo Lucio