Come posso spezzare questa lunga fila in Python?


176

Come faresti a formattare una linea lunga come questa? Vorrei arrivare a non più di 80 caratteri di larghezza:

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

Questa è la mia migliore opzione?

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

1
Sembra una buona opzione. Cosa non ti piace?
Hamish Grubijan,

2
Un po 'soggettivo, no? :)
Adam Woś,

1
correlati: stackoverflow.com/questions/1940710/… (concatenazione di stringhe in pitone)
jldupont

14
È possibile salvare un personaggio rimuovendo l'errato 'in "è".
jball

2
indexes: il plurale corretto di indexè indices.
Scruffy,

Risposte:


336

Questo è un inizio. Non è una cattiva pratica definire le stringhe più lunghe al di fuori del codice che le utilizza. È un modo per separare dati e comportamento. La tua prima opzione è quella di unire i letterali stringa implicitamente rendendoli adiacenti l'uno all'altro:

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

O con le continuazioni di fine riga, che è un po 'più fragile, poiché funziona:

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

Ma questo non:

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

Vedi la differenza? No? Beh, non lo sarà nemmeno quando è il tuo codice.

L'aspetto negativo di unire implicitamente è che funziona solo con letterali di stringa, non con stringhe prese da variabili, quindi le cose possono diventare un po 'più pelose quando si refactoring. Inoltre, puoi solo interpolare la formattazione sulla stringa combinata nel suo insieme.

In alternativa, puoi unirti esplicitamente usando l'operatore di concatenazione ( +):

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

Esplicito è meglio che implicito, come dice lo zen di Python, ma questo crea tre stringhe invece di una e utilizza il doppio della memoria: ci sono le due che hai scritto, più una che sono le due unite insieme, quindi tu devi sapere quando ignorare lo zen. Il lato positivo è che puoi applicare la formattazione a qualsiasi sottostringa separatamente su ogni riga o all'intero lotto al di fuori delle parentesi.

Infine, puoi usare stringhe tra virgolette:

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

Questo è spesso il mio preferito, sebbene il suo comportamento sia leggermente diverso rispetto alla nuova riga e qualsiasi spazio bianco iniziale nelle righe successive verrà visualizzato nella stringa finale. È possibile eliminare la nuova riga con una barra rovesciata in fuga.

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

Questo ha lo stesso problema della stessa tecnica precedente, in quanto il codice corretto differisce dal codice errato solo per gli spazi bianchi invisibili.

Qual è il "migliore" dipende dalla tua situazione particolare, ma la risposta non è semplicemente estetica, ma uno di comportamenti leggermente diversi.


26
Il compilatore CPython ottimizza il più possibile le operazioni letterali, il che significa che l'aggiunta di due valori letterali di stringa comporta un solo valore letterale di stringa nel bytecode.
Ignacio Vazquez-Abrams,

2
Mentre tutte le risposte che ho ricevuto sono utili, le tue sicuramente mi aiutano a capire tutti i modi per spezzare le corde. Il problema con la linea "\" terminava con uno spazio dopo di esso?
Gattster,

1
Non riesco a vedere la differenza qui, ma poi, questo è principalmente a causa della colorazione della sintassi piuttosto primitiva di SO. (Alcuni codici perfettamente validi sono praticamente illeggibili su SO, ma solo perché non sono in una lingua la cui sintassi è molto vicina a C.) Non è insolito fare in modo che il tuo editor evidenzi in modo odioso gli spazi finali, poiché raramente sono utili (o intenzionali) . :-)
Ken

1
@KhurshidAlam potresti usare le virgolette singole 'per contenere quella stringa, oppure sfuggire alle doppie virgolette all'interno della tua stringa, oppure usare le doppie virgolette doppie """. Il problema con stringhe tra virgolette contenenti virgolette è lo stesso sia che si utilizzi una riga singola o più righe per definire la stringa letterale.
hugovdberg,

1
Il mio editor rimuove sempre gli spazi bianchi finali. Ti consiglio di abilitare la stessa impostazione. Ovviamente lo spazio bianco sulla nuova riga fa ancora parte della stringa, quindi ho finito per usare +.
ThaJay

46

I letterali di stringhe consecutivi vengono uniti dal compilatore e le espressioni tra parentesi sono considerate come una singola riga di codice:

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

11

Personalmente non mi piace appendere blocchi aperti, quindi lo formattare come:

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

In generale, non mi preoccuperei di lottare troppo duramente per far sì che il codice si adattasse esattamente a una riga di 80 colonne. Vale la pena mantenere la lunghezza della linea a livelli ragionevoli, ma il limite degli 80 è un ricordo del passato.


8
Non è davvero un ricordo del passato. La libreria standard di Python utilizza ancora PEP8 come guida di stile, quindi la regola esiste ancora e molte persone (me compreso) la seguono. È un posto conveniente per disegnare la linea.
Devin Jeanpierre,

3
Mi chiedo quanti progetti seguano ancora la regola degli 80 caratteri. Per la dimensione media della finestra che uso, penso che 100-120 sia più produttivo per me di 80 caratteri.
Gattster,

1
Sì, riguarda anche la lunghezza della linea che uso, anche se [horror! sacrilegio!] Uso un carattere proporzionale, quindi la lunghezza esatta della linea non è così critica. È più un caso di quanta logica su una singola riga è leggibile di quanti caratteri, in quanto tale ... se ho una lunga serie di dati che nessuno deve leggere sono felice di lasciarlo scorrere 120.
bobince

Caratteri proporzionali per il codice - Sono con te, fratello. A giudicare dal disgusto che tutti quelli con cui ho mai lavorato hanno avuto per loro, il mondo non è pronto.
jlarcombe,

4
~ 80 caratteri facilitano anche la diffusione di 2 file affiancati sullo stesso schermo. Inoltre, se esegui il debug di qualcosa durante un'emergenza terribile sulla console di un server, apprezzerai davvero il limite di 80 caratteri! :)
Mick T

4

Puoi usare il modulo textwrap per romperlo su più righe

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

ABCDEFGH
IJKLIMNO

Dalla documentazione :

textwrap. wrap (text [, width [, ...]])
Avvolge il singolo paragrafo nel testo (una stringa) in modo che ogni riga abbia al massimo caratteri di larghezza. Restituisce un elenco di righe di output, senza newline finali.

Gli argomenti di parole chiave opzionali corrispondono agli attributi di istanza di TextWrapper, documentati di seguito. la larghezza predefinita è 70.

Vedere il TextWrapper.wrap()metodo per ulteriori dettagli su come si comporta wrap ().


2

Per chiunque stia anche cercando di chiamare .format()una stringa lunga e non è in grado di utilizzare alcune delle più popolari tecniche di avvolgimento delle stringhe senza interrompere la .format(chiamata successiva , è possibile eseguire str.format("", 1, 2)invece di "".format(1, 2). Ciò ti consente di spezzare la corda con qualsiasi tecnica ti piaccia. Per esempio:

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

può essere

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

Altrimenti, l'unica possibilità è usare le continuazioni di fine riga, di cui personalmente non sono fan.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.