python - Forma pitónica de crear una larga cadena multilínea.
plot title python (19)
Tengo una consulta muy larga. Me gustaría dividirlo en varias líneas en Python. Una forma de hacerlo en JavaScript sería usar varias oraciones y unirlas con un operador +
(lo sé, tal vez no sea la forma más eficiente de hacerlo, pero no estoy realmente preocupado por el rendimiento en esta etapa, solo la legibilidad del código ). Ejemplo:
var long_string = ''some text not important. just garbage to'' +
''illustrate my example'';
Intenté hacer algo similar en Python, pero no funcionó, así que usé /
para dividir la cadena larga. Sin embargo, no estoy seguro de si esta es la única / mejor / pythonic forma de hacerlo. Se ve incómodo. Código actual:
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
"À la" Scala (pero creo que es la forma más pitónica que exige 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('' | '','' '')
Si desea una línea final sin líneas de salto, simplemente coloque /n
al comienzo del primer argumento de la segunda sustitución:
.replace(''/n | '','' '')`.
Nota: la línea blanca entre "... plantillas". y "Además, ..." requiere un espacio en blanco después de la |
.
¿Estás hablando de cadenas multilínea? Fácil, usa comillas triples para comenzar y terminarlas.
s = """ this is a very
long string if I had the
energy to type more and more ..."""
También puede usar comillas simples (3 de ellas al principio y al final) y tratar la cadena resultante como cualquier otra cadena.
NOTA : Al igual que con cualquier cadena, cualquier cosa entre las comillas iniciales y finales se convierte en parte de la cadena, por lo que este ejemplo tiene un espacio en blanco inicial (como lo indica @ root45). Esta cadena también contendrá tanto espacios en blanco como líneas nuevas.
Es decir,:
'' this is a very/n long string if I had the/n energy to type more and more ...''
Finalmente, uno también puede construir líneas largas en Python como esta:
s = ("this is a very"
"long string too"
"for sure ..."
)
que no incluirá espacios en blanco ni nuevas líneas adicionales (este es un ejemplo deliberado que muestra el efecto de omitir espacios en blanco):
''this is a verylong string toofor sure ...''
No se requieren comas, simplemente coloque las cadenas para unirlas en un par de paréntesis y asegúrese de tener en cuenta los espacios en blanco y las nuevas líneas necesarios.
En Python> = 3.6 puedes usar literales de cadena con formato (cadena 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}''''''
En general, uso la list
y me join
para comentarios / cadenas de varias líneas.
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)
puede usar cualquier cadena para unir todo este elemento de la lista como '' /n
'' (nueva línea) o '' ,
'' (coma) o '' ''(espacio)
Aclamaciones..!!
Encuentro que cuando construyes cadenas largas, usualmente estás haciendo algo como construir una consulta SQL, en cuyo caso es mejor:
query = '' ''.join(( # note double parens, join() takes an iterable
"SELECT foo",
"FROM bar",
"WHERE baz",
))
Lo que Levon sugirió es bueno, pero podría ser vulnerable a errores:
query = (
"SELECT foo"
"FROM bar"
"WHERE baz"
)
query == "SELECT fooFROM barWHERE baz" # probably not what you want
Este enfoque utiliza solo una barra invertida para evitar un salto de línea inicial, casi ninguna puntuación interna mediante el uso de una cadena entre comillas triples, elimina la sangría local mediante el módulo textwrap y también utiliza la interpolación de cadenas formateadas con python 3.6 (''f'') para el account_id
y def_id
variables De esta manera me parece la más pitónica.
import textwrap
query = textwrap.dedent(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}''''''
)
Me encontré feliz con este:
string = """This is a
very long string,
containing commas,
that I split up
for readability""".replace(''/n'','' '')
Me gusta este enfoque porque privilegia la lectura. ¡En los casos en que tenemos cadenas largas no hay manera! Dependiendo del nivel de sangría en el que se encuentre y aún limitado a 80 caracteres por línea ... Bueno ... No es necesario que diga nada más. En mi opinión, las guías de estilo de pitón son todavía muy vagas. Tomé el enfoque de @Eero Aaltonen porque privilegia la lectura y el sentido común. Entiendo que las guías de estilo deben ayudarnos y no hacer de nuestras vidas un desastre. ¡Gracias!
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
)
"""
Me parece que textwrap.dedent
el mejor para cadenas largas como se describe here :
def create_snippet():
code_snippet = textwrap.dedent("""/
int main(int argc, char* argv[]) {
return 0;
}
""")
do_something(code_snippet)
Otra opción que creo que es más legible cuando el código (por ejemplo, la variable) está sangrado y la cadena de salida debe ser de un liner (sin nuevas líneas):
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
Personalmente, considero que la siguiente es la mejor forma (simple, segura y Pythonic) de escribir consultas de SQL sin procesar en Python, especialmente cuando se usa el módulo sqlite3 de 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
Pros
- Código limpio y simple (Pythonic!)
- Seguro de inyección SQL
- Compatible con Python 2 y Python 3 (después de todo, es Pythonic)
- No se requiere concatenación de cuerdas
- No es necesario asegurarse de que el carácter más a la derecha de cada línea sea un espacio
Contras
- Dado que las variables en la consulta son reemplazadas por el
?
marcador de posición, puede ser un poco difícil hacer un seguimiento de cuál?
debe sustituirse por la variable Python cuando hay muchos de ellos en la consulta.
Por ejemplo:
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''
Si el valor de la condición debe ser una cadena, puede hacer esto:
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''"
Romper líneas por /
funciona para mí. Aquí hay un ejemplo:
longStr = "This is a very long string " /
"that I wrote to help somebody " /
"who had a question about " /
"writing long strings in Python"
Si no desea una cadena multilínea pero solo tiene una cadena de una sola línea larga, puede usar paréntesis, solo asegúrese de no incluir comas entre los segmentos de la cadena, entonces será una tupla.
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)
En una declaración de SQL como lo que estás construyendo, las cadenas multilínea también estarían bien. Pero si el espacio en blanco adicional que contendría una cadena multilínea sería un problema, entonces esta sería una buena manera de lograr lo que desea.
También puede colocar la instrucción sql en un archivo separado action.sql
y cargarlo en el archivo py con
with open(''action.sql'') as f:
query = f.read()
Por lo tanto, las sentencias de SQL se separarán del código de Python. Si hay parámetros en la declaración de SQL que deben rellenarse desde Python, puede usar el formato de cadena (como% s o {campo})
También puede concatenar variables al usar la notación "" ":
foo = ''1234''
long_string = """fosdl a sdlfklaskdf as
as df ajsdfj asdfa sld
a sdf alsdfl alsdfl """ + foo + """ aks
asdkfkasdk fak"""
EDIT: Encontró una mejor manera, con params nombrados y .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)
Tu código real no debería funcionar, faltan espacios en blanco al final de "líneas" (por ejemplo: role.descr as roleFROM...
)
Hay citas triples para la cadena multilínea:
string = """line
line2
line3"""
Contendrá los saltos de línea y espacios adicionales, pero para SQL eso no es un problema.
Usualmente uso algo como esto:
text = ''''''
This string was typed to be a demo
on how could we write a multi-line
text in Python.
''''''
Si desea eliminar los espacios en blanco molestos en cada línea, puede hacer lo siguiente:
text = ''/n''.join(line.lstrip() for line in text.splitlines())
Utilizo una función recursiva para construir consultas SQL complejas. Esta técnica generalmente se puede usar para construir cadenas grandes manteniendo la legibilidad del código.
# 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)
PD: Eche un vistazo a la impresionante biblioteca python-sqlparse para imprimir bonitas consultas SQL si es necesario. http://sqlparse.readthedocs.org/en/latest/api/#sqlparse.format