Pythoniczny sposób utworzenia długiego ciągu wieloliniowego


1304

Mam bardzo długie zapytanie. Chciałbym podzielić go na kilka wierszy w Pythonie. Sposobem na zrobienie tego w JavaScript byłoby użycie kilku zdań i połączenie ich z +operatorem (wiem, może nie jest to najskuteczniejszy sposób, ale nie martwię się o wydajność na tym etapie, tylko o czytelność kodu) . Przykład:

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

Próbowałem zrobić coś podobnego w Pythonie, ale to nie zadziałało, więc \dzieliłem długi ciąg. Nie jestem jednak pewien, czy jest to jedyny / najlepszy / pythoniczny sposób na zrobienie tego. Wygląda niezręcznie. Rzeczywisty kod:

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

207
Ponieważ twój przykład wygląda jak blok SQL, który tylko czeka na atak wstrzyknięcia, inną sugestią jest zajrzenie do biblioteki SQL wyższego poziomu, takiej jak SQLAlchemy lub coś, co pozwoli uniknąć hakowania razem surowego SQLa w ten sposób. (Być może nie na temat, ale poprosiłeś o „Wszelkie sugestie”.;)
John Gaines Jr.

6
Jest to „Pythoński sposób tworzenia wieloliniowego kodu dla długiego łańcucha” Aby utworzyć ciąg zawierający znaki nowego wiersza, zobacz textwrap.dedent .
Bob Stein

8
@cezar Napisałem to pytanie ponad pięć lat temu, ale pamiętam, że powstało z tego, że nie umiałem poprawnie umieścić długiego zapytania SQL w kilku wierszach. Zgadzam się, że robiłem głupie rzeczy z tym długim sznurkiem, ale to nie było moje pytanie i nie byłem wystarczająco inteligentny, aby poszukać lepszego przykładu, aby to zilustrować, który nie zawierał pewnych problemów z zastrzykiem sql.
Pablo Mescher

@cezar nie, to nie jest problem XY, zapytanie najlepiej byłoby sformatować w wielu wierszach. SQLi nie ma związku z danym pytaniem. Duże śmiałe ostrzeżenia są jednak całkowicie uzasadnione :)
bugmenot123

Napisałem do tego mały pakiet. Przykład tutaj: stackoverflow.com/a/56940938/1842491
Shay

Odpowiedzi:


2225

Czy mówisz o ciągach wieloliniowych? Łatwe, użyj potrójnych cytatów, aby je rozpocząć i zakończyć.

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

Możesz także używać pojedynczych cudzysłowów (3 z nich oczywiście na początku i na końcu) i traktować wynikowy ciąg znaków stak jak każdy inny ciąg.

UWAGA : Podobnie jak w przypadku dowolnego łańcucha, cokolwiek między początkowymi i końcowymi cudzysłowami staje się częścią łańcucha, tak więc w tym przykładzie znajduje się wiodąca spacja (jak wskazał @ root45). Ten ciąg będzie zawierał zarówno puste, jak i nowe wiersze.

To znaczy,:

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

Wreszcie, w Pythonie można również budować długie linie:

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

który nie będzie zawierał żadnych dodatkowych spacji ani znaków nowej linii (jest to celowy przykład pokazujący, jaki będzie efekt pominięcia spacji):

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

Nie wymaga przecinków, po prostu umieść ciągi, które mają zostać połączone, w nawiasie i upewnij się, że uwzględnisz wszelkie potrzebne spacje i znaki nowej linii.


8
Wolę jawnie używać operatora „+” dla drugiej metody. Niewielki kłopot i poprawia czytelność.
Marco Sulla,

38
@LucasMalor Sąsiadujące ciągi są konkatenacją w czasie kompilacji. Czy użycie +operatora nie powoduje konkatenacji w czasie wykonywania?
Joshua Taylor

13
Dla odniesienia, oto oficjalne dokumenty tego zjawiska: docs.python.org/2/reference/… (python 2) i docs.python.org/3/reference/… (python 3)
neverendingqs

4
Twój przykład jest dobry, ale chciałbym, aby zawierał on demonstrację bezpiecznego i bezpiecznego osadzania zmiennych w zapytaniu. Zarówno przykładowy kod OP, jak i @jessee pokazują, jak NIE robić tego poprawnie (są zaproszeniami na ataki SQL). Zobacz także: dev.mysql.com/doc/connector-python/en/…
Scott Prive,

2
możesz użyć textwrap.dedentdo usunięcia niechcianych wiodących białych znaków. docs.python.org/3/library/textwrap.html#textwrap.dedent
Corey Goldberg

190

Jeśli nie chcesz ciągu wielowierszowego, ale po prostu masz długi ciąg jednego wiersza, możesz użyć nawiasów, po prostu upewnij się, że nie zawierasz przecinków między segmentami ciągów, to będzie krotka.

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)

W instrukcji SQL, takiej jak to, co konstruujesz, łańcuchy wielowierszowe byłyby również w porządku. Ale jeśli dodatkowa spacja, którą miałby ciąg wielowierszowy, stanowiłaby problem, byłby to dobry sposób na osiągnięcie tego, co chcesz.


1
@Pablo możesz nawet dodawać komentarze po,
Ashwini Chaudhary

@ 200OK masz na myśli po '?
kon psych

3
Innym sposobem formatowania tego ciągu byłoby dodanie go .format(...)po nawiasie zamykającym. %notacja formująca też musi działać, ale jeszcze tego nie próbowałem
kon psych

3
Zauważ, że każda linia musi kończyć się ciągiem stałym, więc ' foo '+variablenie będzie działać, ale ' foo '+variable+''będzie.
yoyo

46
Ten przykład to otwarte drzwi do iniekcji SQL. Proszę, nie używaj tego w żadnej publicznej aplikacji. Zobacz dokumentację MySQL, jak używać „ symboli
Scott Prive,

138

Przełamywanie linii \działa dla mnie. Oto przykład:

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

9
Wolałbym notację z potrójnym cytatem lub zawijanie wewnątrz () niż znak \
Khanh Hua

14
Radzę umieścić spacje na początku kolejnych wierszy zamiast na końcu kolejnych wierszy. W ten sposób przypadkowo brakujący jest o wiele bardziej oczywisty (a zatem mniej prawdopodobny).
Alfe,

Działa również ze zmiennymi na końcu liniilongStr = "account: " + account_id + \ ...
frmbelz,

Otrzymuję następujący błąd: the backslash is redundant between bracketskiedy pisałem w środkuprint()
alper

50

Byłem zadowolony z tego:

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

30
Nie zgadzać się. Co jeśli pierwszy wiersz („string = ...”) jest mocno wcięty? Trzeba by było wgniecić następujące linie do zerowania wcięcia, które wygląda brzydko w środku bloku wcięcia.
xjcl

1
Cóż, większość moich długich łańcuchów występuje na poziomie modułu, gdzie ładnie to pasuje. W twoim przypadku nie byłoby to oczywiście najlepsze rozwiązanie.
Eero Aaltonen,

1
Podoba mi się to podejście, ponieważ uprzywilejowuje czytanie. W przypadkach, w których mamy długie łańcuchy, nie ma mowy ... W zależności od poziomu wcięcia, w którym się znajdujesz i nadal jesteś ograniczony do 80 znaków w wierszu ... Cóż ... Nie musisz nic więcej mówić. Moim zdaniem przewodniki w stylu python są nadal bardzo niejasne. Dzięki!
Eduardo Lucio

Byłoby tak brzydki, jeśli jest on stosowany w ramach modułu, muszę jak również.replace('\t','')
alper

44

Uważam, że budując długie ciągi, zwykle robisz coś takiego jak budowanie zapytania SQL, w którym to przypadku najlepiej:

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

To, co sugerował Levon, jest dobre, ale może być podatne na błędy:

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

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

8
+1 Zwalnia recenzenta kodu z konieczności starannego sprawdzania prawego końca każdej linii pod kątem nieodpowiednich białych znaków . OP popełnił ten błąd kilka razy, jak zauważył @KarolyHorvath.
Bob Stein

2
Podczas przeglądania łańcuchów wielowierszowych zakodowanych w podobny sposób, potrzebuję odpowiedniej spacji na lewym końcu każdej linii dla łatwego potwierdzenia.
Parasol

3
@ Recenzje w kodzie BobStein-VisiBone nie powinny dotyczyć błędów składniowych ani takich drobnych błędów, powinny dotyczyć treści. Jeśli ktoś wystawia kod do przeglądu, który ma błędy składniowe (a zatem nie będzie działał wcale lub w pewnych sytuacjach), to coś jest naprawdę nie tak. Nie jest trudno uruchomić kłaczki przed popełnieniem. Jeśli dana osoba nie zauważyła, że ​​jej program nie działa poprawnie, ponieważ popełniła tak oczywisty błąd, nie powinna się angażować.
Charles Addis

1
Uzgodnione @CharlesAddis, recenzje kodu powinny następować po zautomatyzowanych metodach, np. Kłaczków, podświetlaniu składni itp. Jednak niektóre błędy, w których brakuje białych znaków, mogą nie zostać wykryte w ten sposób. Sugeruję skorzystanie ze wszystkich rozsądnych korzyści w ochronie przed błędami.
Bob Stein

33

Możesz także łączyć zmienne, używając notacji „”:

foo = '1234'

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

EDYCJA: Znaleziono lepszy sposób, z nazwanymi parametrami i .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

Podejście to wykorzystuje:

  • tylko jeden odwrotny ukośnik, aby uniknąć początkowego wysuwu wiersza
  • prawie brak wewnętrznej interpunkcji przy użyciu potrójnego cudzysłowu
  • usuwa lokalne wcięcia za pomocą modułu textwrap inspect
  • używa interpolacji ciągów sformatowanych w języku Python 3.6 („f”) dla zmiennych account_idi def_id.

W ten sposób wygląda mi najbardziej pytonicznie.

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

Aktualizacja : 29.01.2019 Włącz sugestię @ ShadowRanger inspect.cleandoczamiasttextwrap.dedent


5
Uwaga: inspect.cleandocjest nieco ładniejszy niż textwrap.dedent, ponieważ nie wymaga, aby pierwsza linia była pusta ze znakiem kontynuacji linii na końcu.
ShadowRanger

2
@ShadowRanger Wow, nigdy wcześniej nie używałem Cleandoc. Zaktualizowałem swoją odpowiedź i w przyszłości będę inspect.cleandocdo tego wykorzystywać .
Christopher Bruns

23

W Pythonie> = 3.6 możesz użyć sformatowanych literałów łańcuchowych (ciąg f)

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

4
Jak działałby ciąg f, gdybym chciał zapisać wynik ciągu wieloliniowego i nie pokazywać tabulacji / spacji po lewej stronie?
kuanb

7
Wciąż podatny na iniekcję SQL
Trenton

19

Na przykład:

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'

jeśli wartość warunku powinna być łańcuchem, możesz to zrobić w następujący sposób:

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

13

Uważam, textwrap.dedentże najlepsze dla długich ciągów, jak opisano tutaj :

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

1
Bardzo podoba mi się czarny ukośnik, który zapobiega automatycznej nowej linii, dzięki bardzo!
zyy

12

Inni wspominali już o metodzie nawiasów, ale chciałbym dodać, że w nawiasach dozwolone są wstawiane komentarze.

Komentarz do każdego fragmentu:

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

Komentarz nie jest dozwolony po kontynuacji:

Podczas korzystania z kontynuacji linii z odwrotnym ukośnikiem ( \) komentarze nie są dozwolone. Otrzymasz SyntaxError: unexpected character after line continuation characterbłąd.

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

Lepsze komentarze do ciągów Regex:

Na podstawie przykładu z 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)

10

Osobiście uważam, że to najlepszy (prosty, bezpieczny i Python) sposób pisania surowych zapytań SQL w Pythonie, szczególnie gdy używa się modułu sqlite3 Pythona :

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

Plusy

  • Zgrabny i prosty kod (Pythonic!)
  • Bezpieczny przed iniekcją SQL
  • Kompatybilny zarówno z Python 2, jak i Python 3 (w końcu jest to Python)
  • Nie wymaga konkatenacji ciągów
  • Nie ma potrzeby upewniania się, że najbardziej po prawej stronie każdej linii jest spacja

Cons

  • Ponieważ zmienne w zapytaniu są zastępowane przez ?symbol zastępczy, śledzenie, ?która zmienna Pythona ma być zastąpiona przez zmienną Python , może być nieco trudne .

Uwaga, nie testowałem tego, ale prawdopodobnie można uniknąć pomyłki znaku zapytania, zastępując je „{0} {1} {2}” w odpowiednich miejscach, a następnie zmieniając ostatnią linię na cursor.execute(query.format(vars)). To powinno zająć się twoim jedynym „oszustwem” (mam nadzieję).
Ben

Tak, użycie formatbyłoby przyjemne, ale nie jestem pewien, czy sformatowany w ten sposób ciąg zapytania byłby bezpieczny przed wstrzyknięciem SQL.
Faheel

Tak, to słuszna kwestia i na pewno może być nieco trudna. Być może przetestowanie go na czymś całkowicie zbędnym byłoby mądre ... bez wątpienia komp. Sci. undergrad wkrótce przeminie. ;)
Ben

2
@Ben, jeśli tego cursor.execute(query.format(vars))nie robisz, nie czerpiesz już korzyści z przygotowanych instrukcji, więc jesteś podatny na różnego rodzaju problemy, zaczynając od faktu, że jeśli parametry nie są tylko liczbami, musisz je podwójnie zacytować w zapytaniu SQL.
Patrick Mevzek,

4

Zwykle używam czegoś takiego:

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

Jeśli chcesz usunąć irytujące puste miejsca w każdej linii, możesz wykonać następujące czynności:

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

2
Zajrzyj do textwrap.dedentfunkcji Pythona , która znajduje się w standardowej bibliotece, ma ona potrzebną funkcjonalność.
bjd2385

@ bjd2385: inspect.cleandocjest nieco ładniejszy (mniej wybredny, czy tekst pojawia się w tym samym wierszu co otwarte cudzysłowy, nie wymaga wyraźnych znaków kontynuacji linii).
ShadowRanger

3

Rzeczywisty kod nie powinien działać, brakuje białych znaków na końcu „wierszy” (np .: role.descr as roleFROM... :)

Istnieją potrójne cytaty dla ciągu wielowierszowego:

string = """line
  line2
  line3"""

Będzie zawierać podział wiersza i dodatkowe spacje, ale w przypadku SQL nie stanowi to problemu.


3

Możesz także umieścić instrukcję sql w osobnym pliku action.sqli załadować ją do pliku py za pomocą

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

Tak więc instrukcje sql zostaną oddzielone od kodu python. Jeśli w instrukcji sql znajdują się parametry, które należy wypełnić z python, możesz użyć formatowania ciągów (np.% S lub {field})


3

Scala „À la” (ale myślę, że jest to najbardziej pythoniczny sposób, jak wymaga OQ):

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

Jeśli chcesz końcowy ciąg bez linii przeskoku, po prostu umieść \nna początku pierwszego argumentu drugiego zastępowania:

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

Uwaga: biała linia między „... szablonami”. i „Ponadto…” wymaga spacji po |.


3

tl; dr: Użyj """\i, """aby zawinąć ciąg , jak w

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

Z oficjalnej dokumentacji Pythona :

Literały łańcuchowe mogą obejmować wiele linii. Jednym ze sposobów jest użycie potrójnych cudzysłowów: „” „…” „” lub „”…… ”. Koniec linii są automatycznie uwzględniane w ciągu, ale można temu zapobiec, dodając \ na końcu linii. Poniższy przykład:

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

tworzy następujące dane wyjściowe (zauważ, że początkowa nowa linia nie jest uwzględniona):

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

2

Hej, spróbuj czegoś takiego, mam nadzieję, że to zadziała, jak w tym formacie zwróci ci ciągłą linię, jakbyś pomyślnie zapytał o tę właściwość`

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

1

Używam funkcji rekurencyjnej do budowania złożonych zapytań SQL. Tę technikę można ogólnie zastosować do budowy dużych ciągów przy zachowaniu czytelności kodu.

# 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: Zajrzyj do niesamowitej biblioteki python-sqlparse, aby w razie potrzeby całkiem wydrukować zapytania SQL. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format


„funkcja rekurencyjna” nie jest tak zwana lambda?
m3nda

1

Inna opcja, która moim zdaniem jest bardziej czytelna, gdy kod (np. Zmienna) jest wcięty, a ciąg wyjściowy powinien być jednowarstwowy (bez znaków nowej linii):

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

Użyj potrójnych cudzysłowów. Ludzie często używają ich do tworzenia dokumentów na początku programów w celu wyjaśnienia ich celu i innych informacji związanych z jego tworzeniem. Ludzie używają ich również w funkcjach, aby wyjaśnić cel i zastosowanie funkcji. Przykład:

'''
Filename: practice.py
File creator: me
File purpose: explain triple quotes
'''


def example():
    """This prints a string that occupies multiple lines!!"""
    print("""
    This
    is 
    a multi-line
    string!
    """)

0

Podoba mi się to podejście, ponieważ uprzywilejowuje czytanie. W przypadkach, gdy mamy długie sznurki, nie ma mowy! W zależności od poziomu wcięcia, w którym się znajdujesz i nadal jesteś ograniczony do 80 znaków w wierszu ... Cóż ... Nie musisz nic więcej mówić. Moim zdaniem przewodniki w stylu python są nadal bardzo niejasne. Przyjąłem podejście @Eero Aaltonen, ponieważ uprzywilejowuje czytanie i zdrowy rozsądek. Rozumiem, że przewodniki po stylu powinny nam pomóc, a nie popsuć nasze życie. Dzięki!

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

Z oficjalnej dokumentacji Pythona :

Literały łańcuchowe mogą obejmować wiele linii. Jednym ze sposobów jest użycie potrójnych cudzysłowów: „” „…” „” lub „”…… ”. Koniec linii są automatycznie uwzględniane w ciągu, ale można temu zapobiec, dodając \ na końcu linii. Poniższy przykład:

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

tworzy następujące dane wyjściowe (zauważ, że początkowa nowa linia nie jest uwzględniona):


0

Aby zdefiniować długi ciąg znaków wewnątrz dykta, zachowując znaki nowej linii, ale pomijając spacje , ostatecznie zdefiniowałem ciąg znaków w następujący sposób:

LONG_STRING = \
"""
This is a long sting
that contains newlines.
The newlines are important.
"""

my_dict = {
   'foo': 'bar',
   'string': LONG_STRING
}

0

Jako ogólne podejście do długich ciągów znaków w Pythonie możesz użyć potrójnych cudzysłowów spliti 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())

Wynik:

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

W odniesieniu do pytania OP dotyczącego zapytania SQL, odpowiedź poniżej pomija poprawność tego podejścia do budowania zapytań SQL i skupia się wyłącznie na budowaniu długich ciągów w czytelny i estetyczny sposób bez dodatkowych importów. Pomija również obciążenie obliczeniowe z tym związane.

Za pomocą potrójnych cudzysłowów budujemy długi i czytelny ciąg, który następnie dzielimy na listę, split()usuwając w ten sposób białe znaki, a następnie łącząc je z powrotem ' '.join(). Na koniec wstawiamy zmienne za pomocą format()polecenia:

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)

Produkuje:

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 = 123 AND record_def.account_id=123 AND def_id=321

Edycja: To podejście nie jest zgodne z PEP8, ale czasami uważam je za przydatne


-7

Ogólnie używam listi joindo wieloliniowych komentarzy / napisów.

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)

możesz użyć dowolnego łańcucha, aby połączyć wszystkie elementy listy, takie jak „ \n(nowa linia) lub ,” (przecinek) lub „ ” (spacja)

Twoje zdrowie..!!


1
Dlaczego nie użyłbyś literału tablicowego?
Alexander - Przywróć Monikę

1
Tablice są reprezentowane przez listę klas. sprawdź kolejną dyskusję dotyczącą literałów tablicowych
paone,

Przypuszczam, że to działa, ale powinieneś pomyśleć o wydajności i czytelności ...
Petro
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.