wake-up-neo.com

Pythonische Methode zum Erstellen einer langen mehrzeiligen Zeichenfolge

Ich habe eine sehr lange Frage. Ich möchte es in Python in mehrere Zeilen aufteilen. Eine Möglichkeit, dies in JavaScript zu tun, besteht darin, mehrere Sätze zu verwenden und sie mit einem + -Operator zu verbinden (ich weiß, es ist möglicherweise nicht die effizienteste Möglichkeit, dies zu tun, aber ich mache mir in dieser Phase keine großen Sorgen über die Leistung , nur Codelesbarkeit). Beispiel:

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

Ich habe versucht, etwas Ähnliches in Python zu tun, aber es hat nicht funktioniert, also habe ich \ verwendet, um den langen String zu teilen. Ich bin mir jedoch nicht sicher, ob dies der einzige/beste/pythonischste Weg ist. Es sieht komisch aus. Tatsächlicher Code:

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
1088
Pablo Mescher

Sprechen Sie über mehrzeilige Zeichenfolgen? Verwenden Sie einfach dreifache Anführungszeichen, um sie zu beginnen und zu beenden.

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

Sie können auch einfache Anführungszeichen verwenden (3 natürlich am Anfang und am Ende) und die resultierende Zeichenfolge s wie jede andere Zeichenfolge behandeln.

NOTE: Wie bei jeder Zeichenfolge wird auch in diesem Beispiel zwischen den Anführungszeichen und den Endanführungszeichen ein Leerzeichen eingefügt (siehe @ root45). Diese Zeichenfolge enthält auch Leerzeichen und Zeilenumbrüche.

Das heißt:

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

Schließlich kann man auch lange Zeilen in Python wie folgt konstruieren:

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

was nicht zusätzliche Leerzeichen oder Zeilenumbrüche enthält (dies ist ein bewusstes Beispiel, das zeigt, wie sich das Überspringen von Leerzeichen auswirkt):

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

Es sind keine Kommas erforderlich. Platzieren Sie einfach die Zeichenfolgen, die miteinander verbunden werden sollen, in Klammern und achten Sie darauf, die erforderlichen Leerzeichen und Zeilenumbrüche zu berücksichtigen.

1877
Levon

Wenn Sie keine mehrzeilige Zeichenfolge, sondern nur eine lange, einzeilige Zeichenfolge möchten, können Sie Klammern verwenden. Achten Sie jedoch darauf, dass zwischen den Zeichenfolgensegmenten keine Kommas stehen. Dann handelt es sich um ein Tupel.

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)

In einer SQL-Anweisung wie der, die Sie erstellen, sind auch mehrzeilige Zeichenfolgen in Ordnung. Aber wenn das zusätzliche Leerzeichen, das eine mehrzeilige Zeichenfolge enthalten würde, ein Problem darstellen würde, wäre dies ein guter Weg, um das zu erreichen, was Sie wollen.

160
Jesse

Das Brechen von Zeilen durch \ funktioniert für mich. Hier ist ein Beispiel:

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

Ich fand mich mit diesem zufrieden:

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

Ich stelle fest, dass Sie beim Erstellen langer Zeichenfolgen normalerweise so etwas wie eine SQL-Abfrage erstellen. In diesem Fall ist dies am besten:

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

Was Levon vorschlug, ist gut, aber möglicherweise fehleranfällig:

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

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

Sie können Variablen auch "" verketten, wenn Sie die Notation "" verwenden:

foo = '1234'

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

EDIT: Einen besseren Weg gefunden, mit named params und .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)
26
gjgjgj

In Python> = 3.6 können Sie Formatierte String-Literale (f-String) verwenden

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

Dieser Ansatz verwendet:

  • nur ein Backslash, um einen Zeilenvorschub zu vermeiden
  • fast keine interne Interpunktion durch Verwendung einer dreifach zitierten Zeichenfolge
  • entfernt lokale Einrückungen mit dem textumbruch inspect Modul
  • verwendet python 3.6 formatierte Zeichenfolgeninterpolation ('f') für die Variablen account_id und def_id.

Dieser Weg sieht für mich am pythonischsten aus.

# 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}'''
)

pdate: 29.01.2013 @ ShadowRangers Vorschlag zur Verwendung von inspect.cleandoc anstelle von textwrap.dedent einbinden

19

Zum Beispiel:

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'

wenn der Wert von condition ein String sein soll, können Sie folgendermaßen vorgehen:

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

Ich persönlich halte Folgendes für die beste (einfache, sichere und pythonische) Methode zum Schreiben von unformatierten SQL-Abfragen in Python, insbesondere bei Verwendung von Pythons sqlite3-Modul :

_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
_

Vorteile

  • Ordentlicher und einfacher Code (Pythonic!)
  • Sicher vor SQL-Injection
  • Kompatibel mit Python 2 und Python 3 (immerhin ist es Pythonic)
  • Keine Zeichenkettenverkettung erforderlich
  • Es muss nicht sichergestellt werden, dass das Zeichen ganz rechts in jeder Zeile ein Leerzeichen ist

Nachteile

  • Da Variablen in der Abfrage durch den Platzhalter _?_ ersetzt werden, kann es etwas schwierig werden, festzustellen, welche _?_ durch welche Python -Variable ersetzt werden soll, wenn es Lose gibt von ihnen in der Abfrage.
9
Faheel Ahmad

Ich finde textwrap.dedent am besten für lange Streicher wie beschrieben hier :

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

Andere haben die Methode der Klammern bereits erwähnt, aber ich möchte hinzufügen, dass Inline-Kommentare mit Klammern zulässig sind.

Kommentar zu jedem Fragment:

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

Kommentar nach Fortsetzung nicht erlaubt:

Bei Verwendung von Backslash-Fortsetzungen (\) sind Kommentare nicht zulässig. Sie erhalten die Fehlermeldung 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

Bessere Kommentare für Regex-Saiten:

Basierend auf dem Beispiel von 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)
5
ddrscott

Normalerweise benutze ich so etwas:

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

Wenn Sie störende Leerzeichen in jeder Zeile entfernen möchten, können Sie wie folgt vorgehen:

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

Dein eigentlicher Code sollte nicht funktionieren, es fehlen Leerzeichen am Ende von "Zeilen" (zB: role.descr as roleFROM...)

Es gibt dreifache Anführungszeichen für mehrzeilige Zeichenfolge:

string = """line
  line2
  line3"""

Es wird die Zeilenumbrüche und zusätzliche Leerzeichen enthalten, aber für SQL ist das kein Problem.

3
Karoly Horvath

Sie können die sql-Anweisung auch in einer separaten Datei action.sql ablegen und mit in die py-Datei laden

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

Die SQL-Anweisungen werden also vom Code python getrennt. Wenn die SQL-Anweisung Parameter enthält, die von Python aus gefüllt werden müssen, können Sie die Formatierung von Zeichenfolgen verwenden (z. B.% s oder {field}).

2
mrijken

"À la" Scala way (aber ich denke, es ist der pythonischste Weg, den OQ verlangt):

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

Wenn Sie einen finalen String ohne Sprungzeilen wollen, setzen Sie einfach \n an den Anfang des ersten Arguments der zweiten Ersetzung:

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

Hinweis: Die weiße Linie zwischen "... Vorlagen". und "Also, ..." erfordert ein Leerzeichen nach dem |.

2
victe

Ich benutze eine rekursive Funktion, um komplexe SQL-Abfragen zu erstellen. Diese Technik kann im Allgemeinen verwendet werden, um große Zeichenfolgen zu erstellen, während die Lesbarkeit des Codes erhalten bleibt.

# 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: Schauen Sie sich die fantastische Python-SQLParse-Bibliothek an, um bei Bedarf hübsche SQL-Abfragen auszudrucken. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format

1
Sandeep

Eine weitere Option, die meiner Meinung nach besser lesbar ist, wenn der Code (z. B. Variable) eingerückt ist und die Ausgabezeichenfolge einzeilig sein sollte (keine Zeilenumbrüche):

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: Verwenden Sie """\ und """, um den String wie in

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

Aus der offiziellen python Dokumentation :

String-Literale können mehrere Zeilen umfassen. Eine Möglichkeit ist die Verwendung von dreifachen Anführungszeichen: "" "..." "" oder '' '...' ''. Das Zeilenende wird automatisch in die Zeichenfolge eingefügt. Sie können dies jedoch verhindern, indem Sie am Zeilenende ein\einfügen. Das folgende Beispiel:

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

erzeugt die folgende Ausgabe (beachten Sie, dass die anfängliche Newline nicht enthalten ist):

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

Aus der offiziellen python Dokumentation :

String-Literale können mehrere Zeilen umfassen. Eine Möglichkeit ist die Verwendung von dreifachen Anführungszeichen: "" "..." "" oder '' '...' ''. Das Zeilenende wird automatisch in die Zeichenfolge eingefügt. Sie können dies jedoch verhindern, indem Sie am Zeilenende ein\einfügen. Das folgende Beispiel:

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

erzeugt die folgende Ausgabe (beachten Sie, dass die anfängliche Newline nicht enthalten ist):

0
Flow

Hey, versuchen Sie etwas wie dieses und hoffen Sie, dass es funktioniert. In diesem Format erhalten Sie eine fortlaufende Zeile, so als hätten Sie sich erfolgreich nach dieser Immobilie erkundigt

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

Ich mag diesen Ansatz, weil er das Lesen privilegiert. In Fällen, in denen wir lange Saiten haben, gibt es keinen Weg! Abhängig von der Einrückungsstufe, in der Sie sich befinden und die immer noch auf 80 Zeichen pro Zeile begrenzt ist ... Nun ... Sie müssen nichts weiter sagen. Meiner Meinung nach sind die python Styleguides immer noch sehr vage. Ich habe den @ Eero Aaltonen-Ansatz gewählt, weil er das Lesen und den gesunden Menschenverstand fördert. Ich verstehe, dass Styleguides uns helfen und unser Leben nicht durcheinander bringen sollten. Vielen Dank!

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