Pythonische manier om een ​​lange string met meerdere regels te maken

Ik heb een erg lange vraag. Ik zou het in Python in verschillende regels willen splitsen. Een manier om het in JavaScript te doen, is door verschillende zinnen te gebruiken en ze samen te voegen met een +-operator (ik weet het, misschien is het niet de meest efficiënte manier om het te doen, maar ik maak me niet echt zorgen over de prestaties in deze fase alleen leesbaarheid van de code). Voorbeeld:

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

Ik heb geprobeerd iets soortgelijks te doen in Python, maar het werkte niet, dus gebruikte ik \ om de lange string te splitsen. Ik weet echter niet zeker of dit de enige/beste/pythonische manier is om het te doen. Het ziet er onhandig uit.
Actuele 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

Antwoord 1, autoriteit 100%

Heb je het over strings met meerdere regels? Eenvoudig, gebruik drievoudige aanhalingstekens om ze te beginnen en te beëindigen.

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

Je kunt ook enkele aanhalingstekens gebruiken (waarvan 3 natuurlijk aan het begin en einde) en de resulterende tekenreeks s net als elke andere tekenreeks behandelen.

OPMERKING: Net als bij elke tekenreeks, wordt alles tussen de aanhalingstekens begin en eind onderdeel van de tekenreeks, dus dit voorbeeld heeft een leidende spatie (zoals aangegeven door @root45). Deze string zal ook zowel spaties als nieuwe regels bevatten.

D.w.z.:

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

Ten slotte kan men in Python ook zo lange regels construeren:

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

die geen extra spaties of nieuwe regels zal bevatten (dit is een bewust voorbeeld dat laat zien wat het effect is van het overslaan van spaties):

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

Geen komma’s vereist, plaats gewoon de tekenreeksen die moeten worden samengevoegd in een paar haakjes en zorg ervoor dat u rekening houdt met eventuele spaties en nieuwe regels.


Antwoord 2, autoriteit 9%

Als u geen tekenreeks met meerdere regels wilt, maar alleen een lange tekenreeks met één regel, kunt u haakjes gebruiken. Zorg ervoor dat u geen komma’s tussen de tekenreekssegmenten plaatst (dan wordt het een 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)

In een SQL-statement zoals u aan het bouwen bent, zouden strings met meerdere regels ook goed zijn. Maar als de extra witruimte die een string met meerdere regels zou bevatten een probleem zou zijn, dan zou dit een goede manier zijn om te bereiken wat je wilt.


Antwoord 3, autoriteit 6%

Breaking lines by \ werkt voor mij. Hier is een voorbeeld:

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

Antwoord 4, autoriteit 2%

Ik was blij met deze:

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

Antwoord 5, autoriteit 2%

Ik merk dat je bij het bouwen van lange strings meestal zoiets doet als het bouwen van een SQL-query, in welk geval dit het beste is:

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

Wat Levon voorstelde is goed, maar kan kwetsbaar zijn voor fouten:

query = (
    "SELECT foo"
    "FROM bar"
    "WHERE baz"
)
query == "SELECT fooFROM barWHERE baz"  # Probably not what you want

Antwoord 6

Deze aanpak gebruikt:

  • bijna geen interne interpunctie door gebruik van een driedubbele tekenreeks tussen aanhalingstekens
  • verwijdert lokale inspringing met behulp van de module inspect
  • gebruikt in Python 3.6 geformatteerde tekenreeksinterpolatie (‘f’) voor de variabelen account_id en def_id.

Deze manier lijkt mij het meest Pythonisch.

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

Antwoord 7

U kunt ook variabelen opnemen bij het gebruik van """ notatie:

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

Een betere manier is, met benoemde parameters en .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)

Antwoord 8

In Python >= 3.6 kun je Geformatteerde letterlijke tekenreeksen gebruiken (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}'''

Antwoord 9

Bijvoorbeeld:

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'

Als de waarde van de voorwaarde een tekenreeks moet zijn, kunt u dit als volgt doen:

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

Antwoord 10

Ik vind textwrap.dedent de beste voor lange strings zoals beschreven hier:

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

Antwoord 11

Anderen hebben de methode met haakjes al genoemd, maar ik wil graag toevoegen dat met haakjes inline opmerkingen zijn toegestaan.

Reageer op elk 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.
)

Commentaar niet toegestaan ​​na vervolg:

Bij gebruik van backslash-lijnvervolgingen (\ ), zijn opmerkingen niet toegestaan. U ontvangt een SyntaxError: unexpected character after line continuation character-fout.

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

Beter commentaar voor Regex-strings:

Gebaseerd op het voorbeeld van 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)

Antwoord 12

Persoonlijk vind ik het volgende de beste (eenvoudige, veilige en pythonische) manier om onbewerkte SQL-query’s in Python te schrijven, vooral bij gebruik van Sqlite3-module van Python:

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

Pluspunten

  • Nette en eenvoudige code (Pythonic!)
  • Veilig tegen SQL-injectie
  • Compatibel met zowel Python 2 als Python 3 (het is tenslotte Pythonic)
  • Geen tekenreeksaaneenschakeling vereist
  • Het is niet nodig om ervoor te zorgen dat het meest rechtse teken van elke regel een spatie is

Nadelen

  • Aangezien variabelen in de query worden vervangen door de tijdelijke aanduiding ?, kan het een beetje moeilijk worden om bij te houden welke ? moet worden vervangen door welke Python-variabele wanneer er zijn er veel in de zoekopdracht.

Antwoord 13

Als algemene benadering van lange strings in Python kun je drievoudige aanhalingstekens, split en join gebruiken:

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

Uitvoer:

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

Met betrekking tot de vraag van OP met betrekking tot een SQL-query, negeert het onderstaande antwoord de juistheid van deze benadering van het bouwen van SQL-query’s en richt het zich alleen op het bouwen van lange strings op een leesbare en esthetische manier zonder extra invoer. Het houdt ook geen rekening met de rekenbelasting die dit met zich meebrengt.

Met behulp van drievoudige aanhalingstekens bouwen we een lange en leesbare reeks die we vervolgens opsplitsen in een lijst met behulp van split(), waarbij we de witruimte verwijderen en deze vervolgens weer samenvoegen met ' '.join(). Ten slotte voegen we de variabelen in met het commando format():

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)

Produceert:

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

Deze aanpak is niet in lijn met PEP 8, maar ik vind het soms wel handig.

Houd er rekening mee dat de accolades in de originele tekenreeks worden gebruikt door de functie format() .


Antwoord 14

Je eigenlijke code zou niet moeten werken; u mist spaties aan het einde van "regels" (bijvoorbeeld role.descr as roleFROM...).

Er zijn drievoudige aanhalingstekens voor tekenreeksen met meerdere regels:

string = """line
  line2
  line3"""

Het bevat de regeleinden en extra spaties, maar voor SQL is dat geen probleem.


Antwoord 15

tl;dr: gebruik """\ en """ om de tekenreeks af te sluiten, zoals in

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

Van de officiële Python-documentatie:

Letterlijke tekenreeksen kunnen meerdere regels beslaan. Een manier is het gebruik van
triple-quotes: """…""" of ”’…”’. Einde van regels worden automatisch
opgenomen in de string, maar het is mogelijk om dit te voorkomen door een . toe te voegen
\ aan het einde van de regel. Het volgende voorbeeld:

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

produceert de volgende uitvoer (merk op dat de initiële nieuwe regel dat niet is)
inbegrepen):

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

Antwoord 16

Ik gebruik meestal zoiets als dit:

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

Als u vervelende spaties in elke regel wilt verwijderen, kunt u het volgende doen:

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

Antwoord 17

Probeer zoiets als dit. Zoals in dit formaat zal het u een ononderbroken regel teruggeven alsof u met succes naar deze eigenschap heeft geïnformeerd:

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

Antwoord 18

U kunt de SQL-instructie ook in een apart bestand, action.sql, plaatsen en in het .py-bestand laden met:

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

Dus de SQL-instructies worden gescheiden van de Python-code. Als er parameters in de SQL-instructie zijn die vanuit Python moeten worden ingevuld, kunt u tekenreeksopmaak gebruiken (zoals %s of {field}).


Antwoord 19

"A la" Scala manier (maar ik denk dat dit de meest Pythonische manier is zoals de OP vereist):

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

Als je de laatste str zonder springlijnen wilt, plaats dan gewoon \n aan het begin van het eerste argument van de tweede vervanging:

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

Opmerking: de witte lijn tussen "…templates." en "Ook,…" vereist een spatie na de |.


Antwoord 20

De ideeën combineren van:

Levon of Jesse , Faheel en ddrscott

met mijn opmaaksuggestie zou je je vraag kunnen schrijven als:

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

Of leuk vinden:

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

Wat interessant zou kunnen zijn samen met ‘IN’ en ‘vars.extend(options) of n_options(len(options))’, waarbij:

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

Of met de hint van darkfeline, dat je nog steeds fouten kunt maken met die voorloopspaties en scheidingstekens en ook met benoemde tijdelijke aanduidingen:

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

Zie documentatie van Cursor.execute-function.

"Dit is de [meest Pythonische] manier!" – …


Antwoord 21

Een andere optie waarvan ik denk dat deze beter leesbaar is wanneer de code (bijvoorbeeld een variabele) is ingesprongen en de uitvoerreeks een one-liner moet zijn (geen nieuwe regels):

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

Antwoord 22

Ik gebruik een recursieve functie om complexe SQL-query’s te bouwen. Deze techniek kan over het algemeen worden gebruikt om grote strings te bouwen met behoud van de leesbaarheid van de code.

# 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: Bekijk de geweldige python-sqlparse bibliotheek om zo nodig mooie SQL-query’s af te drukken.


Antwoord 23

Voor het definiëren van een lange string in een dictaat,
de nieuwe regels behouden maar de spaties weglaten, uiteindelijk definieerde ik de string in een constante zoals deze:

LONG_STRING = \
"""
This is a long sting
that contains newlines.
The newlines are important.
"""
my_dict = {
   'foo': 'bar',
   'string': LONG_STRING
}

Antwoord 24

Ik vind deze aanpak prettig omdat het leesvoorrechten geeft. In gevallen waar we lange snaren hebben, is er geen manier! Afhankelijk van het niveau van inspringing waarin u zich bevindt en nog steeds beperkt tot 80 tekens per regel… Nou… U hoeft verder niets te zeggen

Naar mijn mening zijn de Python-stijlgidsen nog steeds erg vaag. Ik heb de Eero Aaltonen-aanpak gevolgd , omdat het lezen en gezond verstand bevoorrecht. Ik begrijp dat stijlgidsen ons moeten helpen en niet van ons leven een puinhoop moeten maken.

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

Antwoord 25

Van de officiële Python-documentatie:

Letterlijke tekenreeksen kunnen meerdere regels beslaan. Een manier is het gebruik van
triple-quotes: """…""" of ”’…”’. Einde van regels worden automatisch
opgenomen in de string, maar het is mogelijk om dit te voorkomen door een . toe te voegen
\ aan het einde van de regel. Het volgende voorbeeld:

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

produceert de volgende uitvoer (merk op dat de initiële nieuwe regel dat niet is)
inbegrepen):


Antwoord 26

Over het algemeen gebruik ik list en join voor opmerkingen/tekenreeksen van meerdere regels.

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)

Je kunt elke string gebruiken om al deze lijstelementen samen te voegen, zoals ‘\n‘(newline) of ‘,‘(komma) of ‘ ‘(spatie).

LEAVE A REPLY

Please enter your comment!
Please enter your name here

two × 1 =

Other episodes