Python offre un supporto ec­cel­len­te per le ope­ra­zio­ni sulle stringhe e l’ela­bo­ra­zio­ne del testo. Questo lin­guag­gio prevede svariate opzioni per la for­mat­ta­zio­ne e l’output dei testi. Vi pre­sen­tia­mo i prin­ci­pa­li metodi di for­mat­ta­zio­ne delle stringhe in Python.

A quale scopo si uti­liz­za­no i metodi di for­mat­ta­zio­ne delle stringhe in Python?

Le stringhe sono sequenze di caratteri che in Python possono contenere singole lettere, parole, frasi o anche interi documenti. Nella pratica spesso è ne­ces­sa­rio usare metodi per la for­mat­ta­zio­ne delle stringhe, con cui non si intendono as­so­lu­ta­men­te gli elementi visivi come il grassetto in Word. Dunque, di cosa si tratta?

Le stringhe possono essere composte da più pezzi. In molti casi si devono mescolare com­po­nen­ti statici e dati variabili, ad esempio per re­sti­tui­re dati e creare documenti nello sviluppo web.

Prendiamo ad esempio un negozio online. Vogliamo calcolare il prezzo totale dei prodotti nel carrello e mostrarlo all’utente: “Il prezzo totale è di […] euro”. Per prima cosa si può provare a comporre la stringa con l’operatore di con­ca­te­na­zio­ne:

price = 69.42
message = "The total price is" + price + "EUR"
Python

Purtroppo, viene generato un messaggio di errore, perché il prezzo è un numero e non può essere con­ca­te­na­to con una stringa. Dobbiamo quindi prima con­ver­ti­re il numero in una stringa con la funzione str():

message = "The total price is" + str(price) + "EUR"
Python

In questo modo, il codice diventa ve­lo­ce­men­te confuso. Sarebbe meglio definire tutto il testo con i se­gna­po­sti e poi inserire i dati. Per con­ver­ti­re i dati potrebbe essere ne­ces­sa­rio adattarne la for­mat­ta­zio­ne. È proprio questo che fanno i metodi di for­mat­ta­zio­ne delle stringhe in Python.

Come fun­zio­na­no i metodi di for­mat­ta­zio­ne delle stringhe in Python?

Python supporta svariati metodi per la for­mat­ta­zio­ne delle stringhe, ciascuno con i propri vantaggi e svantaggi. Nel tempo il numero di metodi è aumentato, motivo per cui tra loro ci sono molti punti in comune e alcune dif­fe­ren­ze. Vi pre­sen­tia­mo i prin­ci­pa­li metodi di for­mat­ta­zio­ne delle stringhe in Python:

  1. Con l’operatore Modulo
  2. Con il metodo str.format()
  3. Con in­ter­po­la­zio­ne delle stringhe
  4. Con stringhe template

Operatore Modulo

La più vecchia for­mat­ta­zio­ne delle stringhe integrata in Python utilizza l’operatore Python per il segno per­cen­tua­le, al­tri­men­ti uti­liz­za­to per l’ope­ra­zio­ne ma­te­ma­ti­ca modulo. Per questo motivo, il metodo è chiamato anche for­mat­ta­zio­ne delle stringhe Modulo.

Di seguito uti­liz­zia­mo uno schema con tre variabili. I nomi usati sono ir­ri­le­van­ti; li abbiamo scelti per rendere il codice più com­pren­si­bi­le possibile.

Com­po­nen­te Nome
Modello con se­gna­po­sto/i template
Operatore Modulo %
Dati da inserire data
Stringa for­mat­ta­ta message

Per prima cosa definiamo il modello come variabile di stringa con il nome template. All’interno del modello de­ter­mi­nia­mo la posizione del se­gna­po­sto con l’ab­bre­via­zio­ne %s:

template = "The total price is %s"
Python

Definiamo quindi il valore da inserire sotto forma di variabile con il nome data:

data = 69.51
Python

Per eseguire la for­mat­ta­zio­ne della stringa di Python scriviamo il modello della stringa, seguito dall’operatore Modulo, e poi la variabile data. Allo stesso modo as­se­gnia­mo la stringa for­mat­ta­ta alla variabile message:

message = template % data
Python

I dati possono essere una variabile. Ma possiamo uti­liz­za­re anche un letterale o un’espres­sio­ne. L’ope­ra­zio­ne Modulo può essere inserita in un’unica riga. Di seguito un esempio di letterale di stringa inserito al posto del se­gna­po­sto:

message = "Here comes %s" % "Jack"
Python

Un altro esempio: cal­co­lia­mo la somma dei prezzi unitari e inseriamo il prezzo totale nel messaggio. Si applica lo stesso schema. L’operatore Modulo può essere seguito da un’espres­sio­ne.

prices = (42, 69, 51)
message = "The total price is %s" % sum(prices)
Python

A questo punto forse vi starete chiedendo perché come se­gna­po­sto viene usato %s e non sem­pli­ce­men­te il segno per­cen­tua­le. La “s” ha in effetti un si­gni­fi­ca­to par­ti­co­la­re: al momento dell’in­se­ri­men­to, i dati vengono con­ver­ti­ti in una stringa con la funzione str().

In Python per la for­mat­ta­zio­ne delle stringhe sono previste altre ab­bre­via­zio­ni che ad esempio for­mat­ta­no i numeri in modo speciale. Per spiegarlo, prendiamo come esempio il Pi greco. Inseriamo il numero nell’ormai noto se­gna­po­sto %s. L’output contiene 15 cifre decimali:

from math import pi as PI
print("The value of Pi is approximately %s" % PI)
Python

Se invece come se­gna­po­sto uti­liz­zia­mo l’ab­bre­via­zio­ne %g, sono vi­sua­liz­za­te solo cinque cifre decimali:

print("The value of Pi is approximately %g" % PI)
Python

Oltre a %s e %g sono di­spo­ni­bi­li varie altre opzioni, che potete scoprire nella sezione seguente.

Con la for­mat­ta­zio­ne delle stringhe di Python è anche possibile definire e riempire più se­gna­po­sti. In questo caso l’operatore Modulo si aspetta una tupla con tanti valori quanti sono i se­gna­po­sti presenti. I se­gna­po­sti vengono riempiti con i valori:

person = ('John', 42)
message = "My friend %s is %s years old" % person
Python

Come potete vedere, la for­mat­ta­zio­ne con l’operatore Modulo non risulta di facile lettura. Va un po’ meglio se al posto di una tupla tra­smet­tia­mo un di­zio­na­rio (dict) con i dati. In questo caso inseriamo i nomi delle voci del di­zio­na­rio tra parentesi dopo il segno per­cen­tua­le dei se­gna­po­sti. Os­ser­van­do il modello di stringa si vede quali sono i valori previsti:

person = {'name': 'John', 'age': 42}
message = "My friend %(name)s is %(age)s years old" % person
Python

Metodo str.format()

Questo metodo di for­mat­ta­zio­ne delle stringhe di Python è un mi­glio­ra­men­to della for­mat­ta­zio­ne Modulo, ori­gi­na­ria­men­te contenuta in Python 3 e poi tra­sfe­ri­ta a Python 2.6. Anziché uti­liz­za­re un operatore speciale, si ricorre a un metodo orientato all’oggetto. Così str.format() è coerente con gli altri metodi per le stringhe come la funzione str.split di Python.

Lo schema di base del metodo str.format() di Python somiglia alla for­mat­ta­zio­ne con l’operatore Modulo ed esiste in forma simile anche in .NET e Rust. Come se­gna­po­sto nelle stringhe template si usano le parentesi graffe, i dati vengono trasmessi come argomenti della chiamata della funzione:

template = "Here comes {}"
data = 'Jack'
message = template.format(data)
Python

Se la stringa template contiene più se­gna­po­sti, passiamo di con­se­guen­za molti argomenti:

message = "My friend {} is {} years old".format('John', 42)
Python

Op­zio­nal­men­te spe­ci­fi­chia­mo la posizione degli argomenti da integrare come indice. È così possibile sganciare la sequenza dei se­gna­po­sti dagli argomenti. Tenete presente che gli indici iniziano con zero:

message = "My friend {1} is {0} years old".format(69, 'Jim')
Python

Se i singoli valori si trovano in una struttura di dati, uti­liz­zia­mo l’operatore asterisco prima dell’argomento per de­com­pri­me­re la struttura di dati. Questa ope­ra­zio­ne funziona con le liste e le tuple:

person = ('John', 42)
message = "My friend {} is {} years old".format(*person)
Python

Nelle stringhe più lunghe, i se­gna­po­sti che non dicono nulla aumentano ve­lo­ce­men­te la con­fu­sio­ne. È meglio uti­liz­za­re argomenti de­no­mi­na­ti:

template = "My friend {name} is {age} years old"
message = template.format(name = 'Jack', age = 51)
Python

Con molti valori la lista degli argomenti di­ven­te­reb­be molto lunga e di con­se­guen­za poco chiara. È quindi meglio rag­grup­pa­re i valori in un di­zio­na­rio da de­com­pri­me­re alla chiamata della funzione. A dif­fe­ren­za delle liste e delle tuple, per de­com­pri­me­re un di­zio­na­rio uti­liz­zia­mo un asterisco doppio:

# define dict
person = {'name': 'Jim', 'age': 69}
# define string with placeholders
template = "My friend {name} is {age} years old"
# unpack dict in `format()` call
message = template.format(**person)
Python

Una par­ti­co­la­ri­tà della for­mat­ta­zio­ne delle stringhe in Python con str.format() è rap­pre­sen­ta­ta dalle svariate opzioni di for­mat­ta­zio­ne. Oltre ad ampliare le funzioni della for­mat­ta­zio­ne Modulo, sono par­ti­co­lar­men­te potenti per l’output del testo nella riga di comando e per i dati tabulari. Di seguito vi pre­sen­tia­mo i mec­ca­ni­smi per la for­mat­ta­zio­ne dei numeri.

Python offre un controllo preciso per re­sti­tui­re numeri sotto forma di testo. Si può così definire come deve essere vi­sua­liz­za­to il segno dei numeri. Per i numeri decimali è inoltre possibile de­ter­mi­na­re il numero di cifre dopo la virgola. È utile per la rap­pre­sen­ta­zio­ne in tabella di numeri positivi o negativi.

Im­ma­gi­nia­mo di voler re­sti­tui­re mi­su­ra­zio­ni della tem­pe­ra­tu­ra:

samples = [('A0147D', 27.6), ('X1489M', -4.7), ('P9921U', -10.93)]
for sample in samples:
    print('| {} | {} |'.format(*sample))
Python

L’output risulta di­sal­li­nea­to perché i numeri sono di lunghezza diversa:

| A0147D | 27.6 |
| X1489M | -4.7 |
| P9921U | -10.93 |
Bash

Adattiamo il codice e definiamo una serie di opzioni di for­mat­ta­zio­ne:

for sample in samples:
    print('| {} | {: 6.2f} |'.format(*sample))
Python

Ora l’output è corretto:

| A0147D | 27.60 |
| X1489M | -4.70 |
| P9921U | -10.93 |
Bash

Ana­liz­zia­mo più da vicino le opzioni di for­mat­ta­zio­ne del secondo se­gna­po­sto. Sono inserite dopo i due punti e com­pren­do­no quattro com­po­nen­ti:

  1. Spazio: mette uno spazio davanti ai numeri positivi per com­pen­sa­re il posto occupato dal segno meno dei numeri negativi.
  2. Numero prima del punto: numero delle lettere di­spo­ni­bi­li com­ples­si­va­men­te per il numero.
  3. Numero dopo il punto: numero di cifre decimali, even­tual­men­te riempito con zeri.
  4. Lettera “f” prima della parentesi graffa di chiusura: formatta il numero come cifra decimale.

Sono di­spo­ni­bi­li svariate altre opzioni di for­mat­ta­zio­ne per gestire con pre­ci­sio­ne l’output di numeri e stringhe. Sono tuttavia usate piuttosto raramente; all’oc­cor­ren­za con­sul­ta­te la do­cu­men­ta­zio­ne sulla for­mat­ta­zio­ne delle stringhe in Python.

In­ter­po­la­zio­ne delle stringhe

A partire da Python 3.6, come metodo di for­mat­ta­zio­ne è di­spo­ni­bi­le anche l’in­ter­po­la­zio­ne delle stringhe. Questo metodo, noto anche come “f-string”, è il più comodo e il più per­for­man­te per molte ap­pli­ca­zio­ni. Il nome deriva dalla sintassi generale; queste stringhe iniziano con la lettera “f”, posta subito prima delle vir­go­let­te di apertura.

Come se­gna­po­sti si usano le parentesi graffe. A dif­fe­ren­za dei metodi pre­ce­den­te­men­te pre­sen­ta­ti, i se­gna­po­sti non con­ten­go­no l’indice o nomi, ma un’espres­sio­ne a piacere. Nella de­fi­ni­zio­ne delle f-string, questi vengono riempiti im­me­dia­ta­men­te:

message = f"40 + 2 equals {40 + 2}"
Python

L’espres­sio­ne può anche essere il nome di una variabile:

name = 'Jack'
message = f"Here comes {name}"
Python

È possibile integrare senza problemi diverse espres­sio­ni:

prices = (42, 69, 51)
currency = 'EUR'
message = f"The total price is {sum(prices)} {currency}"
Python

Stringhe template

Oltre ai tre metodi il­lu­stra­ti, Python supporta anche la for­mat­ta­zio­ne con le stringhe template. Create da una propria classe, pro­teg­go­no dalle falle di sicurezza generate dall’utente.

Le pos­si­bi­li­tà di for­mat­ta­zio­ne all’interno delle stringhe template sono limitate. Anziché espres­sio­ni a piacere, i se­gna­po­sti possono contenere soltanto nomi di variabili. Per via della loro sem­pli­ci­tà, le stringhe template sono l’ideale per l’in­ter­na­zio­na­liz­za­zio­ne delle stringhe in diverse lingue.

Come se­gna­po­sto si usa il simbolo del dollaro, seguito dal nome della variabile da inserire. La sintassi delle stringhe template somiglia quindi a quella dei linguaggi shell come Bash o Zsh. Per inserire il valore si richiama il metodo sub­sti­tu­te():

# import `Template` class from `string` module
from string import Template
# instantiate template
template = Template("Hey there, I'm $name")
# perform substitution
message = template.substitute(name = 'Jack')
Python

Come nei linguaggi shell, c’è un’altra sintassi per i se­gna­po­sti. Il simbolo del dollaro è seguito da parentesi graffe che con­ten­go­no il nome della variabile. Si possono ef­fet­tua­re so­sti­tu­zio­ni all’interno di una parola:

template = Template("Let's buy $amount ${fruit}s")
message = template.substitute(amount = 3, fruit = 'orange')
Python

Quale metodo scegliere per la for­mat­ta­zio­ne delle stringhe in Python?

I singoli metodi pre­sen­ta­no proprietà spe­ci­fi­che che rie­pi­lo­ghia­mo qui:

Metodo Schema Se­gna­po­sto Vantaggi
For­mat­ta­zio­ne Modulo template % data %, %(key) In Python versione < 2.6
str.format() template.format(data) {}, {index}, {key} Per for­mat­ta­zio­ni complesse
f-string f“{ex­pres­sion}“ {ex­pres­sion} Per molte stringhe
Stringa template template.sub­sti­tu­te(data) ${iden­ti­fier} Se le stringhe sono originate dall’utente
Vai al menu prin­ci­pa­le