1704

非常に長いクエリがあります。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
4

30 に答える 30

2850

複数行の文字列について話しているのですか?簡単です。開始と終了には三重引用符を使用します。

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

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

于 2012-05-18T22:22:54.710 に答える
260

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

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 ステートメントでは、複数行の文字列も問題ありません。ただし、複数行の文字列に含まれる余分な空白が問題になる場合、これは目的を達成するための良い方法です。

コメントに記載されているように、この方法で SQL クエリを連結すると、SQL インジェクションのセキュリティ リスクが発生する可能性があるため、データベースのパラメーター化されたクエリ機能を使用してこれを防止してください。ただし、それ以外の場合は、尋ねられた質問に直接回答するため、回答をそのままにしておきます。

于 2012-05-18T22:26:35.373 に答える
170

改行\は私にとってはうまくいきます。次に例を示します。

longStr = "This is a very long string " \
        "that I wrote to help somebody " \
        "who had a question about " \
        "writing long strings in Python"
于 2014-06-20T16:16:55.663 に答える
59

私はこれに満足していることに気づきました:

string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace('\n',' ')
于 2013-01-04T10:39:29.597 に答える
57

長い文字列を作成するときは、通常、SQL クエリを作成するようなことを行っていることがわかりました。その場合、これが最適です。

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

Levonが提案したことは良いことですが、間違いに対して脆弱である可能性があります:

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

query == "SELECT fooFROM barWHERE baz"  # Probably not what you want
于 2014-06-19T07:06:24.120 に答える
48

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

  • 三重引用符で囲まれた文字列を使用することにより、内部の句読点がほとんどありません
  • inspectモジュールを使用してローカル インデントを取り除きます
  • account_idおよび変数に Python 3.6 形式の文字列補間 ('f') を使用しdef_idます。

この方法は、私には最も Pythonic に見えます。

import inspect

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}'''
)
于 2018-06-07T16:58:29.713 に答える
41

""" 表記を使用する場合、変数を含めることもできます。

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)
于 2015-10-06T22:33:07.997 に答える
22

例えば:

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'"
于 2016-05-12T12:05:08.100 に答える
5

実際のコードは機能しないはずです。「行」の末尾に空白がありません (たとえば、role.descr as roleFROM...)。

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

string = """line
  line2
  line3"""

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

于 2012-05-18T22:25:30.547 に答える
4

次のアイデアを組み合わせます。

LevonまたはJesseFaheelddrscott

私のフォーマットの提案では、クエリを次のように書くことができます。

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

または次のように:

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

これは、'IN' および 'vars.extend(options) または n_options(len(options))' と一緒に興味深いものになる可能性があります。

def n_options(count):
    return '(' + ','.join(count*'?') + ')'

または、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

Cursor.execute-function のドキュメントを参照してください。

「これが [最も Pythonic] な方法です!」- ...

于 2020-11-18T02:48:22.790 に答える
3

SQLステートメントを別のファイルに配置action.sqlし、次のコマンドを使用して.pyファイルにロードすることもできます。

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

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

于 2012-05-21T22:25:13.500 に答える
3

コード (変数など) がインデントされていて、出力文字列が 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
于 2016-09-19T13:32:22.417 に答える
1

再帰関数を使用して複雑な 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)

PS: 素晴らしいpython-sqlparseライブラリを見て、必要に応じて SQL クエリをきれいに出力してください。

于 2015-04-09T00:39:22.633 に答える
0

読む特権があるので、私はこのアプローチが好きです。長い文字列がある場合、方法はありません! インデントのレベルにもよりますが、それでも 1 行あたり 80 文字に制限されています...まあ...他に何も言う必要はありません

私の見解では、Python スタイル ガイドはまだ非常に曖昧です。私はエーロ・アールトーネンのアプローチを採用しました。スタイルガイドは私たちを助けるべきであり、私たちの生活を台無しにするべきではないことを理解しています.

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
)
"""
于 2017-06-01T12:58:19.057 に答える