2.5. Metodi delle stringhe e formattazione

Le stringhe dispongono di una cassetta degli attrezzi integrata di metodi per l’ispezione e la rielaborazione. Poiché le stringhe sono immutabili, ogni metodo restituisce una nuova stringa: l’originale resta invariato.

2.5.1. Ispezionare le stringhe

  • str.startswith() / str.endswith() – verifica di prefisso o suffisso; restituisce un bool.

  • str.find() – posizione della prima occorrenza di una sottostringa, oppure -1 se assente. str.index() fa la stessa cosa ma solleva ValueError in caso di assenza.

  • str.count() – numero di occorrenze non sovrapposte.

  • Parola chiave in"MV" in name restituisce True se la sottostringa è presente in un qualsiasi punto della stringa.

>>> name = "OpenMV Cam"
>>> name.startswith("Open")
True
>>> name.find("MV")
4
>>> name.count("m")
1
>>> "Cam" in name
True

2.5.2. Pulizia e maiuscole/minuscole

  • str.strip() – rimuove gli spazi iniziali e finali. Passa una stringa di caratteri per rimuovere un insieme personalizzato (s.strip("/")).

  • str.lower() / str.upper() – conversione tra maiuscole e minuscole.

  • str.replace() – sostituzione di sottostringhe.

>>> "  hello  ".strip()
'hello'
>>> "abc-123".replace("-", "_")
'abc_123'
>>> "OpenMV".lower()
'openmv'

2.5.3. Suddividere e unire

  • str.split() – spezza una stringa in una lista a ogni occorrenza di un separatore (predefinito: qualsiasi sequenza di spaziatura).

  • str.join() – l’inverso: incolla una sequenza di stringhe usando come separatore la stringa su cui viene chiamato. È il modo efficiente per costruire una stringa lunga a partire da varie parti.

>>> "1,2,3".split(",")
['1', '2', '3']
>>> "hello world".split()
['hello', 'world']
>>> ", ".join(["a", "b", "c"])
'a, b, c'

2.5.4. f-string

Il modo più semplice per interpolare valori in una stringa è la f-string: una stringa letterale preceduta da f. Qualsiasi espressione all’interno di {} viene valutata e inserita:

>>> name = "OpenMV"
>>> count = 42
>>> f"{name} saw {count} blobs"
'OpenMV saw 42 blobs'

Due punti all’interno delle parentesi graffe introducono una specifica di formato che controlla come viene rappresentato il valore:

  • {x:.2f} – float con 2 cifre dopo il punto decimale.

  • {x:>10} – allineamento a destra in un campo di 10 caratteri.

  • {x:<10} – allineamento a sinistra.

  • {x:0>4} – riempimento con zeri iniziali fino alla larghezza 4.

  • {x:#x} – esadecimale con un prefisso 0x.

  • {x:b} – rappresentazione binaria.

>>> f"pi is roughly {3.14159:.3f}"
'pi is roughly 3.142'
>>> f"reg = {0xAB:#x}"
'reg = 0xab'
>>> for i in range(3):
...     print(f"line {i:0>3}")
line 000
line 001
line 002

Un singolo = dopo il nome dell’espressione stampa sia il nome sia il valore – comodo per stampe di debug rapide:

>>> v = 3.14
>>> print(f"{v=}")
v=3.14

2.5.4.1. Conversioni di base degli interi

Tre funzioni built-in svolgono lo stesso compito delle specifiche di formato :b / :o / :x ma restituiscono direttamente la stringa convertita:

  • bin() – base 2, con un prefisso "0b".

  • oct() – base 8, con un prefisso "0o".

  • hex() – base 16, con un prefisso "0x".

>>> hex(255)
'0xff'
>>> bin(10)
'0b1010'
>>> oct(8)
'0o10'

La direzione inversa – trasformare una stringa in base N di nuovo in un intero – usa il costruttore int con una base esplicita:

>>> int("ff", 16)
255
>>> int("0b1010", 2)         # the "0b" prefix is allowed
10

Ricorri a queste quando vuoi la stringa grezza di un intero (per una riga di log, un file di configurazione, un dump di registri). Ricorri alla specifica di formato quando vuoi padding, larghezza o mescolare il valore con altro testo nella stessa f-string.

2.5.5. Stili di formattazione più vecchi

Le f-string sono lo stile consigliato, ma due approcci più vecchi funzionano ancora e compaiono nel codice esistente:

str.format() – parentesi graffe con argomenti posizionali o keyword passati al metodo .format() su una stringa template:

>>> "Hello, {}".format(name)
'Hello, OpenMV'
>>> "{0} + {0} = {1}".format(2, 4)
'2 + 2 = 4'
>>> "{name}: {value}".format(name="frames", value=42)
'frames: 42'

Le specifiche di formato ({:.2f}, {:>10}, …) funzionano allo stesso modo delle f-string; l’unica differenza è dove viene fornito il valore.

Formattazione con % (stile printf) – un singolo operatore % sostituisce i valori nei codici di formato, un valore per codice. Passa più valori come tupla:

>>> "Hello, %s" % name
'Hello, OpenMV'
>>> "%d + %d = %d" % (2, 2, 4)
'2 + 2 = 4'
>>> "%.2f" % 3.14159
'3.14'

I codici di tipo più comuni sono %s (stringa), %d (intero), %f (float) e %x (esadecimale).

Ogni codice % può portare dei modificatori tra il % e la lettera di tipo. La forma completa è %[flags][width][.precision]type:

  • width – numero minimo di caratteri che il campo deve occupare. I valori più corti vengono riempiti con spazi; quelli più lunghi traboccano. %10d riserva 10 caratteri e allinea il numero a destra.

  • precision – il significato dipende dal tipo. Per i float, il numero di cifre dopo il punto decimale. %.2f dà due cifre decimali. Per le stringhe, il numero massimo di caratteri da prendere (%.5s tronca a cinque).

  • Allineamento a sinistra – il flag - posiziona il campo a sinistra. %-10d mette le cifre sul lato sinistro con spazi finali.

  • Riempimento con zeri – il flag 0 riempie con zeri iniziali invece che con spazi (per i tipi numerici). %05d riempie di zeri fino a cinque cifre.

  • Segno – il flag + mostra sempre il segno sui numeri, incluso un + per i positivi.

  • Forma alternativa – il flag #. Per %x antepone all’output 0x; per %o antepone 0o.

Flag, larghezza e precisione possono essere combinati:

>>> "%10d" % 42
'        42'                 # width 10, space-padded, right-aligned
>>> "%-10d|" % 42
'42        |'                # width 10, left-aligned
>>> "%05d" % 42
'00042'                      # width 5, zero-padded
>>> "%8.2f" % 3.14159
'    3.14'                   # width 8, 2 decimal places
>>> "%08.2f" % 3.14159
'00003.14'                   # width 8, zero-padded
>>> "%+d" % 42
'+42'                        # explicit sign
>>> "%#06x" % 0xAB
'0x00ab'                     # 0x prefix, zero-pad to 6 chars total

Entrambi gli stili più vecchi sono più lenti da leggere e più soggetti a errori rispetto alle f-string: ricorri alle f-string nel codice nuovo e impara a riconoscere le forme più vecchie quando leggi codice esistente.