Tracce
/
Python
Python
/
Programma
/
Formattazione di stringhe
Fo

Formattazione di stringhe in Python

1 esercizio

Informazioni su Formattazione di stringhe

Formattazione delle stringhe in Python

La formattazione delle stringhe è il processo di conversione di valori in stringhe e di inserimento di questi in un modello di stringa. Lo Zen di Python afferma che dovrebbe esserci «un solo modo ovvio per fare qualcosa in Python». Ma quando si parla di formattazione delle stringhe, le cose sono un po'... meno zen.

Può sorprendere scoprire che esistono quattro modi principali per eseguire la formattazione delle stringhe in Python, ognuno pensato per uno scenario diverso. In parte è dovuto alla lunga storia di Python, in parte a considerazioni come l'internazionalizzazione o la sanificazione degli input. Cominceremo dalle aggiunte più recenti alla cassetta degli attrezzi della formattazione delle stringhe e procederemo a ritroso fino alla formattazione «old style» o «in stile printf()».

Interpolazione di stringhe letterali: la f-string

Introdotte in Python 3.6, le f-string (abbreviazione di «formatted strings») o l'interpolazione di stringhe letterali sono un modo per valutare (e formattare) rapidamente ed efficientemente espressioni e stringhe in un tipo str, usando il prefisso f (o F) prima delle virgolette (così: f'{object}').

Le f-string si possono usare con tutti i tipi di stringa che le racchiudono, come quelle a riga singola (' o ") e multi-riga (''' o """). Qualsiasi variabile, espressione o altro tipo inserito dentro le {} viene prima valutato, poi convertito in una str e infine concatenato con le str al di fuori delle parentesi graffe.

In questo esempio inseriamo due valori di variabili in una frase (una str e un float):

>>> name = 'eighth'
>>> value = 1/8

# The f-string, using the two values.
# The .2f format code truncates, so the value displays as 0.12.
>>> f'An {name} is approximately {value:.2f}.'
'An eighth is approximately 0.12.'

Le espressioni valutate possono essere quasi qualsiasi cosa. Alcune delle (ampie) possibilità che si possono valutare: str, numeri, variabili, espressioni aritmetiche, espressioni condizionali, tipi integrati, slice, funzioni, lambda, comprensioni, o qualsiasi oggetto con metodi __str__ o __repr__ definiti.

Passiamo dal semplice al complesso:

Inserire una variabile: l'uso più semplice di una f-string è mettere una variabile direttamente nella stringa.

# Assigning a variable.
>>> name = "World"

# Inserting that variable.
>>> f'Hello, {name}!'
'Hello, World!'

Espressioni dentro le {}: qualsiasi espressione Python valida può essere valutata dentro le parentesi graffe. Nota che usare le virgolette doppie dentro una f-string racchiusa tra virgolette singole (o viceversa) evita la necessità di sequenze di escape:

# A dictionary of key:value pairs.
>>> waves = {'water': 1, 'light': 3, 'sound': 5}

# Inserting the whole dict.
>>> f'Wave ranks: {waves}'
"Wave ranks: {'water': 1, 'light': 3, 'sound': 5}"

# An expression can be evaluated inline:
>>> f"Tenfold the value of 'light' is {waves['light'] * 10}."
"Tenfold the value of 'light' is 30."

# A method call can also be evaluated inline:
>>> f'{"hello world!".title()} is a classic greeting.'
'Hello World! is a classic greeting.'

# An f-string can be nested inside another f-string:
>>> f"{f'hello world!'.title()} is a classic greeting."
'Hello World! is a classic greeting.'

Formattazione dell'output: il mini-linguaggio di specifica del formato si può usare per controllare l'allineamento, la precisione numerica e molto altro. La specifica di formato va dopo il valore, separata da un :.

# Right-align a value to ten characters, and round it to 3 decimal places.
>>> value = 1 / 7
>>> f'One seventh is {value:10.3f}.'
'One seventh is      0.143.'

# A format specification can be set using variables as well.
>>> padding = 10
>>> precision = 3
>>> f'One seventh is {value:{padding}.{precision}f}.'
'One seventh is      0.143.'

Mettiamo tutto insieme: variabili, espressioni, chiamate di funzione e formattazione dell'output:

>>> precision = 3
>>> f"{30e8 * 111_000:6.{precision}e}"
'3.330e+14'

>>> verb = 'meet'
>>> the_end = ['end', 'of', 'transmission']
>>> f'"Have a {"NICE".lower()} day, I will {verb} you after {30e8 * 111_000:6.{precision}e} light-years."{the_end}'
'"Have a nice day, I will meet you after 3.330e+14 light-years."[\'end\', \'of\', \'transmission\']'

# Did you notice the escaped single-quotes in the previous example?
# Using double quotes instead of single quotes for the f-string means the list's single-quoted strings print cleanly.
>>> f"Have a nice day. {the_end}"
"Have a nice day. ['end', 'of', 'transmission']"

Ci sono due limitazioni principali di cui tenere conto. Le espressioni dentro le f-string non possono essere vuote. Inoltre, prima di Python 3.12, non potevano contenere commenti.

>>> f"An empty expression will error: {}"
SyntaxError: f-string: empty expression not allowed

>>> word = 'word'
>>> f"""A comment in a triple quoted f-string: {
    word # I chose a nice variable
}"""
'A comment in a triple quoted f-string: word'
Caution

L'interpolazione di stringhe non può essere usata insieme all'API GNU gettext per l'internazionalizzazione (I18N) e la localizzazione (L10N), quindi si raccomanda di usare la classe string.Template o il metodo str.format() descritto sotto al posto di una f-string in tutti gli scenari di traduzione con «string wrapping».

Tieni anche presente che usare espressioni dentro le parentesi {} di una f-string è simile a usare eval() o exec(), quindi non è molto sicuro e non dovrebbe mai essere usato con input dell'utente.

Il metodo str.format()

Il metodo str.format() sostituisce i segnaposto all'interno della stringa con i valori passati come argomenti alla funzione. I segnaposto sono identificati da nomi ({price}), numeri ({0} o indici) o anche segnaposto (posizionali) vuoti {}.

Per esempio:

# A named placeholder and a positional placeholder.
>>> 'My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder')
'My text: named placeholder and 12.'

Come per le f-string, il metodo str.format() di Python supporta tutta una gamma di specificatori del mini-linguaggio di formato che si possono usare per allineare il testo, troncare i numeri in virgola mobile e altro ancora.

Lo schema completo di uno specificatore di formato è {[<name>][!<conversion>][:<format_specifier>]}:

  • <name> può essere un segnaposto con nome, un numero o vuoto.
  • !<conversion> è opzionale e deve essere una di queste tre conversioni: !s per str(), !r per repr() o !a per ascii(). Per impostazione predefinita si usa str().
  • :<format_specifier> è opzionale e controlla come viene visualizzato il valore. Maggiori informazioni sulle opzioni possibili si possono trovare qui.

Esempio di conversioni per una lettera diacritica:

# Fills in the object at index zero, converted to a string.
>>> 'An e with an umlaut: {0!s}'.format('ë')
'An e with an umlaut: ë'


# Fills in the object at index zero, converted to a repr.
>>> 'An e with an umlaut (object representation): {0!r}'.format('ë')
"An e with an umlaut (object representation): 'ë'"


# Fills in the object at index zero, converted to ASCII.
>>> 'An e with an umlaut converted into ASCII: {0!a}'.format('ë')
"An e with an umlaut converted into ASCII: '\xeb'"


# Fills in the object in the first position,
# then fills in the object in the second position formatted as a repr.
>>> 'She said her name is not {} but {!r}.'.format('Chloe', 'Zoë')
"She said her name is not Chloe but 'Zoë'."

Esempi di specificatori di formato comuni:

# Integer and binary/hex representations of the same number.
>>> my_num = 42
>>> f"{my_num} in binary is {my_num:b}. In hex, it is {my_num:x}"
"42 in binary is 101010. In hex, it is 2a"

# Alignment: left (<), right (>), and center (^) using up to ten characters total.
>>> f"[{"left":<10}] [{"right":>10}] [{"center":^10}]"
"[left      ] [     right] [  center  ]"

# Float precision and scientific notation (up to three decimal places).
>>> pi = 3.141592653589793
>>> f"Fixed: {pi:.3}  Scientific: {pi:.3e}"
"Fixed: 3.142  Scientific: 3.142e+00"

# Thousands separator and percentage.
>>> balance = 1000
>>> rate = 0.0225
>>> f"Balance: ${balance:,.0f}  Interest rate: {rate:.1%}"
"Balance: $1,000  Interest rate: 2.2%"

# Putting it all together:
>>> items = [("Widget", 1250, 9.991), ("Gadget", 37, 24.503), ("Doohickey", 4, 149.002)]
>>> header = f"{"Item":<12} {"Qty":>6} {"Price":>9}"
>>> print(header)
Item            Qty     Price
>>> for name, qty, price in items:
...     print(f"{name:<12} {qty:>6} {price:>9.2f}")
Widget         1250      9.99
Gadget           37     24.50
Doohickey         4    149.00

Altri esempi sono mostrati alla fine di questa documentazione.

La formattazione con %, o formattazione in stile printf()

L'uso dell'operatore % per la formattazione è il metodo più antico di formattazione delle stringhe in Python. Deriva dal linguaggio C e consente di usare argomenti posizionali per costruire una str.

Questo metodo è stato soppiantato sia dalle f-string sia da str.format(), ed è per questo che il soprannome della formattazione % è «Old Style». Si può ancora trovare in Python 2 e/o in codice legacy. Sebbene usare questo metodo funzioni in Python 3.x, di solito la formattazione % si evita perché può essere soggetta a errori, è meno efficiente, ha meno opzioni disponibili e qualsiasi mancata corrispondenza tra segnaposto e argomento può sollevare un'eccezione. Usare l'operatore % è simile a printf(), quindi a volte viene anche chiamata «formattazione printf».

# Assigning a variable.
>>> name = "Anna-conda"

# Building a string using %.
>>> "The snake's name is %s." % name
"The snake's name is Anna-conda."

Nell'esempio sopra, l'operatore % sostituisce il segnaposto %s con la variabile name in fase di esecuzione. Se vuoi aggiungere più variabili a una stringa, devi fornire una tupla contenente un oggetto per ogni segnaposto dopo il %:

# Assigning variables.
>>> name = "Billy the Kid"
>>> fruit = "grapes"

# Building a string using %.
>>> "Surprisingly, %s's favorite snack was %s." %(name, fruit)
"Surprisingly, Billy the Kid's favorite snack was grapes."

Stringhe interpolate

string.Template() (da non confondere con le t-strings di Python 3.14) è una classe del modulo string (a differenza del tipo integrato str), che fa parte della libreria standard di Python ma va importata per essere usata. Le stringhe interpolate supportano la sostituzione basata su $ e sono molto più semplici e meno potenti delle altre opzioni qui menzionate. Tuttavia, possono essere molto utili per internazionalizzazioni complesse o per sanificare input esterni.

string.Template è considerato più sicuro per input utente non attendibili perché impedisce di valutare espressioni arbitrarie o di accedere agli attributi degli oggetti, il che mitiga gli attacchi di iniezione delle format string.

>>> from string import Template

>>> name = "Anna-Conda"

# Creating a Template with placeholder text.
>>> template_string = Template("The snake called `$snake_name` has escaped!")

# Calling .substitute() to replace the placeholder with a value.
>>> template_string.substitute(snake_name=name)
'The snake called `Anna-Conda` has escaped!'

Ulteriori informazioni su string.Template si possono trovare nella documentazione di Python.

Come scegliere quale metodo di formattazione usare?

Con tutte queste opzioni e mini-linguaggi, come fai a decidere a cosa ricorrere quando formatti stringhe in Python? Ecco alcune linee guida rapide:

  1. Le f-string sono le più recenti e le più facili da leggere. Se non hai bisogno di internazionalizzare, dovrebbero essere il metodo preferito per Python 3.6+.

  2. str.format() è versatile, potente e compatibile sia con gnu gettext sia con la maggior parte delle versioni di Python.

  3. Se ciò che ti serve è semplicità, sicurezza e/o un'intensa internazionalizzazione, puoi usare string.Template() per mitigare i rischi quando devi gestire input degli utenti e per il wrapping delle stringhe di traduzione.

  4. L'operatore % è generalmente considerato deprecato per il codice nuovo, anche se funziona ancora nel Python moderno. Dovrebbe essere usato soprattutto per la compatibilità con basi di codice più vecchie. La formattazione % è più soggetta a errori (e ha meno funzionalità) rispetto agli altri metodi, e può causare problemi con la visualizzazione di caratteri non ASCII. Se intendi usarla, controlla la tua distribuzione specifica di Python per i dettagli sul supporto.

Se vuoi andare più a fondo, tutto sulla formattazione e le buone pratiche per la formattazione delle stringhe in Python sono buoni punti di partenza.

Modifica tramite GitHub Il collegamento si apre in una nuova finestra o scheda