¿Cómo puedo romper esta larga línea en Python?

176

¿Cómo harías para formatear una línea larga como esta? Me gustaría llegar a no más de 80 caracteres de ancho:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

¿Es esta mi mejor opción?

url = "Skipping {0} because its thumbnail was already in our system as {1}."
logger.info(url.format(line[indexes['url']], video.title))
Gattster
fuente
1
Parece una buena opción. ¿Qué no te gusta de eso?
Hamish Grubijan el
2
Un poco subjetivo, ¿no? :)
Adam Woś
1
relacionado: stackoverflow.com/questions/1940710/… (concatenación de cadenas en python)
jldupont
14
Podrías guardar un personaje eliminando el 'incorrecto en "es".
jball
2
indexes: el plural correcto de indexes indices.
Desaliñado

Respuestas:

336

Eso es un comienzo. No es una mala práctica definir sus cadenas más largas fuera del código que las usa. Es una forma de separar datos y comportamiento. Su primera opción es unir cadenas literales juntas implícitamente haciéndolas adyacentes entre sí:

("This is the first line of my text, "
"which will be joined to a second.")

O con continuaciones de final de línea, que es un poco más frágil, ya que esto funciona:

"This is the first line of my text, " \
"which will be joined to a second."

Pero esto no:

"This is the first line of my text, " \ 
"which will be joined to a second."

¿Ver la diferencia? ¿No? Bueno, tampoco lo harás cuando sea tu código.

La desventaja de la unión implícita es que solo funciona con literales de cadena, no con cadenas tomadas de variables, por lo que las cosas pueden ponerse un poco más difíciles cuando refactoriza. Además, solo puede interpolar el formato en la cadena combinada como un todo.

Alternativamente, puede unirse explícitamente utilizando el operador de concatenación ( +):

("This is the first line of my text, " + 
"which will be joined to a second.")

Explícito es mejor que implícito, como dice el zen de python, pero esto crea tres cadenas en lugar de una, y usa el doble de memoria: están las dos que ha escrito, más una, que son las dos juntas, por lo que Hay que saber cuándo ignorar el zen. Lo bueno es que puede aplicar formato a cualquiera de las subcadenas por separado en cada línea, o a todo el lote desde fuera de los paréntesis.

Finalmente, puede usar cadenas entre comillas triples:

"""This is the first line of my text
which will be joined to a second."""

Este es a menudo mi favorito, aunque su comportamiento es ligeramente diferente ya que la nueva línea y cualquier espacio en blanco inicial en las líneas posteriores se mostrarán en su cadena final. Puede eliminar la nueva línea con una barra invertida de escape.

"""This is the first line of my text \
which will be joined to a second."""

Esto tiene el mismo problema que la misma técnica anterior, ya que el código correcto solo difiere del código incorrecto por el espacio en blanco invisible.

Cuál es el "mejor" depende de su situación particular, pero la respuesta no es simplemente estética, sino de comportamientos sutilmente diferentes.

jcdyer
fuente
26
El compilador CPython optimiza las operaciones literales tanto como sea posible, lo que significa que agregar dos literales de cadena da como resultado un solo literal de cadena en el código de bytes.
Ignacio Vazquez-Abrams
2
Si bien todas las respuestas que he recibido son útiles, la suya definitivamente me ayuda a comprender todas las formas de separar los hilos. ¿El problema con el final de la línea "\" era que había un espacio después?
Gattster
1
No puedo ver la diferencia aquí, pero eso se debe principalmente a la coloración de sintaxis bastante primitiva de SO. (Algunos códigos perfectamente buenos son prácticamente ilegibles en SO, pero solo porque no están en un lenguaje cuya sintaxis esté muy cerca de C.) No es inusual hacer que su editor resalte de manera desagradable los espacios finales, ya que rara vez son útiles (o intencionales) . :-)
Ken
1
@KhurshidAlam, podría usar comillas simples 'para contener esa cadena, o escapar de las comillas dobles dentro de su cadena, o usar las comillas dobles triples """. El problema con las cadenas entre comillas que contienen comillas es el mismo si usa una sola línea o varias líneas para definir la cadena literal.
hugovdberg
1
Mi editor elimina los espacios en blanco finales siempre. Te recomiendo que habilites la misma configuración. Por supuesto, el espacio en blanco en la nueva línea sigue siendo parte de la cadena, así que terminé usando +.
ThaJay
46

El compilador une los literales de cadena consecutivos y las expresiones entre paréntesis se consideran una sola línea de código:

logger.info("Skipping {0} because it's thumbnail was "
  "already in our system as {1}.".format(line[indexes['url']],
  video.title))
Ignacio Vazquez-Abrams
fuente
11

Personalmente no me gusta colgar bloques abiertos, así que lo formatearía como:

logger.info(
    'Skipping {0} because its thumbnail was already in our system as {1}.'
    .format(line[indexes['url']], video.title)
)

En general, no me molestaría en esforzarme demasiado para que el código se ajuste exactamente dentro de una línea de 80 columnas. Vale la pena mantener la longitud de la línea a niveles razonables, pero el límite de 80 es cosa del pasado.

bobince
fuente
8
No es realmente una cosa del pasado. La biblioteca estándar de Python todavía usa PEP8 como su guía de estilo, por lo que la regla aún existe, y muchas personas (incluido yo mismo) la siguen. Es un lugar conveniente para trazar la línea.
Devin Jeanpierre el
3
Me pregunto cuántos proyectos siguen la regla de los 80 caracteres. Para el tamaño de ventana promedio que uso, creo que 100-120 es más productivo para mí que 80 caracteres.
Gattster
1
Sí, esa es la longitud de la línea que uso también, aunque [horror! sacrilegio!] Uso una fuente proporcional, por lo que la longitud exacta de la línea no es tan crítica. Es más un caso de cuánta lógica en una sola línea es legible que cuántos caracteres, como tal ... si tengo una larga cadena de datos que nadie necesita leer, estoy feliz de dejar que se desborde 120.
bobince
Fuentes proporcionales para el código: estoy contigo, hermano. Sin embargo, a juzgar por el desagrado que todos con los que he trabajado han tenido por ellos, el mundo no está listo.
jlarcombe
44
~ 80 caracteres también hacen que sea más fácil diferenciar 2 archivos uno al lado del otro en la misma pantalla. Además, si está depurando algo durante una emergencia extrema en la consola de un servidor, ¡realmente apreciará el límite de 80 caracteres! :)
Mick T
4

Puede usar el módulo textwrap para dividirlo en varias líneas

import textwrap
str="ABCDEFGHIJKLIMNO"
print("\n".join(textwrap.wrap(str,8)))

ABCDEFGH
IJKLIMNO

De la documentación :

ajuste de texto. wrap (text [, width [, ...]])
Envuelve el párrafo individual en texto (una cadena) para que cada línea tenga como máximo caracteres de ancho. Devuelve una lista de líneas de salida, sin nuevas líneas finales.

Los argumentos opcionales de palabras clave corresponden a los atributos de instancia de TextWrapper, documentados a continuación. ancho predeterminado a 70.

Consulte el TextWrapper.wrap()método para obtener detalles adicionales sobre cómo se comporta wrap ().

Saurabh
fuente
2

Para cualquier persona que también esté tratando de invocar .format()una cadena larga y no pueda utilizar algunas de las técnicas de ajuste de cadena más populares sin interrumpir la .format(llamada posterior , puede hacerlo en str.format("", 1, 2)lugar de hacerlo "".format(1, 2). Esto le permite romper la cuerda con la técnica que desee. Por ejemplo:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

puede ser

logger.info(str.format(("Skipping {0} because its thumbnail was already"
+ "in our system as {1}"), line[indexes['url']], video.title))

De lo contrario, la única posibilidad es usar continuaciones de final de línea, de las cuales personalmente no soy fanático.

Simon Alford
fuente