Formattazione delle stringhe in Python
Impara i tre metodi di formattazione in Python: operatore %, str.format() e f-string, con esempi su numeri, allineamento, date e altro.
La formattazione delle stringhe consente di costruire stringhe in modo dinamico inserendo variabili, espressioni e valori calcolati in un template. Python offre tre approcci distinti: l'operatore % (legacy), il versatile metodo str.format() e la moderna sintassi delle f-string, ognuno con i propri punti di forza e casi d'uso appropriati.
Questo capitolo tratta:
- Quando usare ciascun metodo di formattazione e perché
- L'operatore
%(legacy, ancora comune nei log e nelle basi di codice più vecchie) str.format()con segnaposto posizionali e nominati- Le f-string (l'approccio moderno consigliato)
- Specificatori di formato: larghezza, allineamento, precisione, riempimento, segno e base
- Formattazione di numeri, percentuali, date e orari
- Errori comuni e casi limite
Per un approfondimento specifico sulle f-string — incluse le espressioni, la logica condizionale e i miglioramenti di Python 3.12 — consulta il capitolo Python f-Strings.
Quale metodo usare?
| Metodo | Versione Python | Quando usarlo |
|---|---|---|
Operatore % | 2.x / 3.x | Codice legacy, modulo logging, sostituzioni molto semplici |
str.format() | 2.6+ | Quando servono format string riutilizzabili o argomenti con nome |
| f-string | 3.6+ | Nuovo codice — le più veloci, le più leggibili, supportano espressioni inline |
A meno che tu non stia mantenendo codice Python 2 o una base di codice Python 3 più vecchia, usa le f-string. Vengono valutate a runtime, non producono overhead aggiuntivo nelle chiamate e mantengono il nome della variabile accanto al punto in cui appare nella stringa.
L'operatore % (formattazione legacy)
L'operatore % sostituisce i valori in una format string usando specificatori di conversione in stile C.
Specificatori di conversione comuni:
| Specificatore | Significato |
|---|---|
%s | String (chiama str() sul valore) |
%d | Intero con segno |
%f | Numero in virgola mobile |
%r | repr() del valore |
%% | Un carattere % letterale |
Larghezza e precisione con %
Puoi controllare la larghezza del campo e la precisione decimale direttamente nello specificatore:
pi = 3.14159265
print("%10.3f" % pi) # right-aligned in a 10-char field, 3 decimal places
# 3.142
print("%-10.3f|" % pi) # left-aligned
# 3.142 |
print("%010.3f" % pi) # zero-padded
# 000003.142Attenzione: valori singoli vs. tuple
Quando si sostituisce un singolo valore, passare una tupla è l'approccio sicuro:
value = "hello"
# Risky — if value were itself a tuple, this would fail:
# print("Got: %s" % value)
# Safe:
print("Got: %s" % (value,))
# Got: hellostr.format() — formattazione flessibile con segnaposto
Il metodo str.format() ha sostituito l'operatore % a partire da Python 2.6+. Utilizza {} come segnaposto e supporta argomenti posizionali, indicizzati e con nome.
Segnaposto posizionali e indicizzati
Segnaposto nominati (con parola chiave)
I segnaposto nominati rendono le format string auto-documentanti e sono particolarmente utili quando lo stesso valore compare più volte o quando la format string proviene da un file di configurazione.
Riutilizzo delle format string
Poiché str.format() accetta una stringa come input, puoi memorizzare il template in una variabile e riutilizzarlo:
template = "Hello, {name}! You have {count} new messages."
print(template.format(name="Alice", count=3))
print(template.format(name="Bob", count=0))
# Hello, Alice! You have 3 new messages.
# Hello, Bob! You have 0 new messages.f-String — formattazione moderna in Python
Le f-string (letterali stringa formattati) antepongono f o F alla stringa e valutano qualsiasi espressione all'interno di {} a runtime. Sono disponibili da Python 3.6 in poi e rappresentano l'approccio consigliato per il nuovo codice.
name = "John"
age = 25
print(f"My name is {name} and I am {age} years old.")
# My name is John and I am 25 years old.Le f-string supportano qualsiasi espressione Python valida all'interno delle parentesi graffe — operazioni aritmetiche, chiamate a metodi, condizionali e altro ancora:
items = ["apple", "banana", "cherry"]
print(f"Cart has {len(items)} items. First: {items[0].upper()}.")
# Cart has 3 items. First: APPLE.
x = -7
print(f"Absolute value: {abs(x)}")
# Absolute value: 7Consulta Python f-Strings per la guida completa, incluso il debug con =, le f-string multiriga e i miglioramenti di Python 3.12.
Specificatori di formato: il mini-linguaggio
Sia str.format() che le f-string utilizzano lo stesso mini-linguaggio per le specifiche di formato all'interno di {} dopo i due punti:
{[field_name]:[fill][align][sign][#][0][width][grouping][.precision][type]}La tabella seguente mostra le opzioni più utili:
| Opzione | Carattere | Effetto |
|---|---|---|
| Allineamento | < > ^ | Sinistra, destra, centro |
| Riempimento | qualsiasi carattere | Riempie il padding (usato con allineamento e larghezza) |
| Segno | + - | Mostra + per i positivi; solo meno per default; spazio per i positivi |
| Prefisso | # | 0x per esadecimale, 0o per ottale, 0b per binario |
| Zero-padding | 0 | Riempie con zeri invece di spazi |
| Larghezza | intero | Larghezza minima del campo |
| Raggruppamento | , o _ | Separatore delle migliaia |
| Precisione | .n | Cifre decimali (float) o numero massimo di caratteri (stringhe) |
| Tipo | d f e g x o b % | Intero, float, notazione scientifica, generale, esadecimale, ottale, binario, percentuale |
Allineamento e larghezza
text = "hello"
print(f"{text:<10}|") # left-aligned in 10-char field
# hello |
print(f"{text:>10}|") # right-aligned
# hello|
print(f"{text:^10}|") # centered
# hello |
print(f"{text:*^10}|") # centered, filled with *
# **hello***|Gli stessi specificatori di allineamento funzionano con str.format(). Ecco un esempio che combina allineamento e precisione:
Formattazione dei numeri
x = 123.456789
print(f"{x:.2f}") # two decimal places
# 123.46
print(f"{x:,.2f}") # thousands separator, two decimal places
# 123.46
print(f"{x:+.2f}") # explicit plus sign for positive numbers
# +123.46
print(f"{x:10.2f}") # right-aligned in a 10-char field
# 123.46
print(f"{x:<10.2f}|") # left-aligned
# 123.46 |
print(f"{x:010.2f}") # zero-padded to 10 characters
# 0000123.46Numeri grandi e percentuali
population = 8_100_000_000
print(f"{population:,}") # comma separator
# 8,100,000,000
print(f"{population:_}") # underscore separator (Python 3.6+)
# 8_100_000_000
ratio = 0.8567
print(f"{ratio:.1%}") # percentage, one decimal place
# 85.7%Basi numeriche degli interi
n = 255
print(f"{n:d}") # decimal (default)
# 255
print(f"{n:x}") # lowercase hexadecimal
# ff
print(f"{n:X}") # uppercase hexadecimal
# FF
print(f"{n:#x}") # hex with 0x prefix
# 0xff
print(f"{n:o}") # octal
# 377
print(f"{n:b}") # binary
# 11111111
print(f"{n:#b}") # binary with 0b prefix
# 0b11111111Puoi usare gli stessi specificatori anche con str.format():
Notazione scientifica
avogadro = 6.02214076e23
print(f"{avogadro:.3e}") # scientific notation, 3 decimal places
# 6.022e+23
print(f"{avogadro:.3E}") # uppercase E
# 6.022E+23
print(f"{avogadro:.3g}") # general: compact form, removes trailing zeros
# 6.02e+23Formattazione delle stringhe con format() e f-string
Tutti e tre gli approcci producono lo stesso output per una semplice sostituzione:
Gli specificatori specifici per le stringhe ti permettono di controllare il troncamento e il padding:
s = "Python"
print(f"{s:.3}") # truncate to 3 characters
# Pyt
print(f"{s:10}") # pad to width 10 (left-aligned by default for strings)
# Python
print(f"{s:>10}") # right-aligned
# Python
print(f"{s:*^12}") # centered, filled with *
# ***Python***Formattazione di date e orari
Usa i codici di formato strftime all'interno delle parentesi graffe quando formatti oggetti datetime con f-string o str.format():
import datetime
date = datetime.datetime(2024, 3, 15, 10, 30, 0)
# Default string representation
print(f"Default: {date}")
# Default: 2024-03-15 10:30:00
# strftime codes inside the format spec
print(f"Formatted: {date:%B %d, %Y}")
# Formatted: March 15, 2024
print(f"Time only: {date:%H:%M:%S}")
# Time only: 10:30:00
print(f"ISO-style: {date:%Y-%m-%d}")
# ISO-style: 2024-03-15La stessa sintassi funziona con str.format():
import datetime
date = datetime.datetime(2024, 3, 15, 10, 30, 0)
print("The date is {:%B %d, %Y}".format(date))
# The date is March 15, 2024Per la formattazione avanzata delle date, consulta il capitolo Python Modify Strings che illustra le tecniche di manipolazione delle stringhe.
Tecniche avanzate
Espressioni annidate nelle f-string
Le f-string ti consentono di calcolare dinamicamente lo specificatore di formato:
width = 10
precision = 3
value = 3.14159
print(f"{value:{width}.{precision}f}")
# output: 3.142 (right-aligned in a 10-char field, 3 decimal places)Specificatore di formato con format() e variabili
La stessa tecnica funziona con str.format() usando {} annidati:
width = 8
print("{:{width}}".format("left", width=width))
# left Formattazione condizionale nelle f-string
Poiché le f-string valutano qualsiasi espressione, puoi usare espressioni condizionali inline:
score = 73
label = f"{'pass' if score >= 60 else 'fail'}"
print(f"Score {score}: {label}")
# Score 73: passDebug con = (Python 3.8+)
Aggiungi = all'interno di una f-string per stampare sia l'espressione che il suo valore — molto utile per il debug:
x = 42
y = x * 2
print(f"{x=}, {y=}")
# x=42, y=84Errori comuni
1. Escape delle parentesi graffe. Per includere un carattere { o } letterale in qualsiasi stringa formattata, raddoppialo:
print(f"Use {{curly braces}} in f-strings")
# Use {curly braces} in f-strings2. Virgolette all'interno delle f-string. In Python 3.11 e versioni precedenti, l'espressione all'interno di {} non può usare lo stesso tipo di virgolette della f-string esterna:
names = ["Alice", "Bob"]
# Wrong in Python <= 3.11:
# print(f"First: {names[0].upper()}") -- this is fine
# print(f"{'Alice'.upper()}") -- single quotes inside double-quoted f-string is fine
# But nesting the same quotes fails:
# print(f"{names["Alice"]}") -- SyntaxError in <= 3.11
# Safe approach for <= 3.11:
key = "Alice"
print(f"{key.upper()}")
# ALICE3. La trappola della tupla con %. Quando si usa la formattazione % con un singolo valore che è esso stesso una tupla, racchiudila in un'altra tupla:
coords = (10, 20)
# This raises TypeError because % sees a 2-element tuple:
# print("Position: %s" % coords)
# Fix: wrap in a 1-element tuple
print("Position: %s" % (coords,))
# Position: (10, 20)4. str.format() e sicurezza. Non passare mai input non attendibile dell'utente come format string a str.format() — un template malevolo può accedere agli attributi degli oggetti e far trapelare dati. Le f-string sono sempre stringhe scritte nel codice, quindi non sono vulnerabili a questo problema.
Confronto pratico
Ecco lo stesso output prodotto da tutti e tre i metodi affiancati:
item = "widget"
qty = 42
unit_price = 4.5
# % operator
print("%-12s %4d $%7.2f" % (item, qty, unit_price))
# str.format()
print("{:<12} {:>4} ${:>7.2f}".format(item, qty, unit_price))
# f-string
print(f"{item:<12} {qty:>4} ${unit_price:>7.2f}")
# All print:
# widget 42 $ 4.50Riepilogo
- Usa le f-string per il nuovo codice Python 3.6+: sono le più leggibili e le più veloci.
- Usa
str.format()quando hai bisogno di un template string riutilizzabile o devi supportare Python 2.6+. - Usa
%solo nel codice legacy o quando lavori con il modulologging(che rimanda la formattazione fino a quando la voce di log viene effettivamente emessa). - Il mini-linguaggio per le specifiche di formato (
width,precision,align,fill,type) si applica allo stesso modo sia astr.format()che alle f-string.
Capitoli correlati:
- Python f-Strings — approfondimento sulle espressioni f-string e le funzionalità di Python 3.12
- Python Strings — fondamenti delle stringhe, indicizzazione e slicing
- Modify Strings — metodi integrati delle stringhe
- Escape Characters — caratteri speciali nelle stringhe