Lezione 3: Tecniche avanzate di manipolazione delle stringhe
La manipolazione delle stringhe è una competenza fondamentale per qualsiasi sviluppatore che utilizza Python. Non solo è essenziale per lo sviluppo di software su larga scala, ma è anche cruciale in campi come la data science, l’intelligenza artificiale e altri settori tecnologici avanzati. In questa sezione, esploreremo le operazioni di base con le stringhe, evidenziando dettagli e informazioni chiave che ogni programmatore dovrebbe conoscere.
Le operazioni di base con le stringhe in Python includono la concatenazione, la ripetizione, lo slicing e l’interpolazione.
Concatenazione di stringhe avviene tramite l’operatore +
, permettendo di unire facilmente due o più stringhe:
stringa1 = "Ciao, " stringa2 = "mondo!" risultato = stringa1 + stringa2 print(risultato) # Output: Ciao, mondo!
Ripetizione delle stringhe usando l’operatore *
:
stringa = "Python " risultato = stringa * 3 print(risultato) # Output: Python Python Python
Slicing per estrarre porzioni di una stringa utilizzando l’operatore []
:
stringa = "Hello, World!" sottostringa = stringa[7:12] print(sottostringa) # Output: World
Introduzione delle f-string (formatted string) in Python 3.6 per una formattazione più chiara delle stringhe:
nome = "Alice" eta = 30 messaggio = f"Ciao, mi chiamo {nome} e ho {eta} anni." print(messaggio) # Output: Ciao, mi chiamo Alice e ho 30 anni.
Uso avanzato di metodi e funzioni built-in per la manipolazione delle stringhe
Padroneggiare metodi e funzioni built-in avanzate può migliorare notevolmente la qualità e l’efficienza del codice. In questa sezione, ci concentreremo su tecniche avanzate per la manipolazione delle stringhe, fornendo dettagli ed esempi pratici.
Metodi Built-in Avanzati
Python offre metodi come strip()
, split()
, join()
, replace()
e format()
per lavorare con le stringhe.
Il metodo strip()
rimuove spazi bianchi o caratteri specifici all’inizio e alla fine di una stringa:
stringa = "**Hello, World!**" risultato = stringa.strip("*") print(risultato) # Output: Hello, World!
Il metodo split()
divide una stringa in una lista, basandosi su un separatore:
testo = "apple,banana,cherry,dates" frutta = testo.split(",") print(frutta) # Output: ['apple', 'banana', 'cherry', 'dates']
Il metodo join()
unisce una lista di stringhe in una singola stringa con un delimitatore:
frutta = ['apple', 'banana', 'cherry', 'dates'] delimitatore = " - " frutta_stringa = delimitatore.join(frutta) print(frutta_stringa) # Output: apple - banana - cherry - dates
Utilizzo di replace()
e format()
Il metodo replace()
sostituisce occorrenze di una sottostringa con un’altra:
testo = "Il prezzo è di $100" nuovo_testo = testo.replace("$", "€") print(nuovo_testo) # Output: Il prezzo è di €100
Il metodo format()
per la formattazione delle stringhe:
nome = "Bob" eta = 25 messaggio = "Ciao, mi chiamo {} e ho {} anni.".format(nome, eta) print(messaggio) # Output: Ciao, mi chiamo Bob e ho 25 anni.
Espressioni regolari (regex) in Python
Le espressioni regolari, comunemente note come regex, sono strumenti potenti e versatili per la manipolazione avanzata delle stringhe in Python. Utilizzando il modulo re
, è possibile effettuare operazioni complesse come ricerca, sostituzione e divisione basate su pattern specifici.
Esempio di estrazione di tutte le parole da una stringa:
import re testo = "Hello, World! Benvenuti nel mondo di Python." parole = re.findall(r'\b\w+\b', testo) print(parole) # Output: ['Hello', 'World', 'Benvenuti', 'nel', 'mondo', 'di', 'Python']
In questo esempio, l’espressione regolare r'\b\w+\b'
viene utilizzata per trovare tutte le parole nella stringa. Ecco come funziona:
\b
indica un confine di parola (inizio o fine di una parola).\w+
corrisponde a uno o più caratteri alfanumerici (una parola).- Combinando questi elementi, l’espressione cerca sequenze di caratteri alfanumerici delimitate da confini di parola.
Uso di quantificatori non greedy:
import re testo = "<div><p>Paragrafo</p></div>" match = re.search(r'<.*?>', testo) print(match.group()) # Output: <div>
In questo esempio, vogliamo estrarre il primo tag HTML dalla stringa. L’espressione regolare r'<.*?>'
viene utilizzata per raggiungere questo obiettivo. Vediamo come funziona:
<
e>
sono caratteri letterali che rappresentano l’inizio e la fine di un tag HTML..*?
è un quantificatore non greedy:.
corrisponde a qualsiasi carattere (tranne il carattere di nuova linea per impostazione predefinita).*
indica “zero o più occorrenze” del carattere precedente.?
rende il quantificatore non greedy, cioè cerca il match più breve possibile.
Senza il quantificatore non greedy, usando r'<.*>'
, l’espressione regolare sarebbe greedy e abbinerebbe il match più lungo possibile:
match = re.search(r'<.*>', testo) print(match.group()) # Output: <div><p>Paragrafo</p></div>
Come si può vedere, l’espressione greedy cattura tutto dal primo <
all’ultimo >
, includendo tutto il contenuto interno. Questo potrebbe non essere desiderato se si vuole estrarre solo il primo tag.
Utilizzando il quantificatore non greedy *?
, l’espressione si ferma al primo match che soddisfa il pattern, cioè il primo <div>
.
Esempio di utilizzo con re.findall()
:
tags = re.findall(r'<.*?>', testo) print(tags) # Output: ['<div>', '<p>', '</p>', '</div>']
Qui, l’espressione regolare con il quantificatore non greedy permette di trovare tutti i tag HTML nella stringa, poiché si ferma dopo ogni tag individuale invece di estendersi al match più lungo possibile.
Quantificatori greedy (golosi) tentano di abbinare il maggior numero possibile di caratteri. Nel caso di .*
, l’espressione corrisponde a qualsiasi carattere ripetuto zero o più volte, espandendosi il più possibile all’interno dei limiti definiti.
Quantificatori non greedy (non golosi), come .*?
, cercano di abbinare il minor numero possibile di caratteri necessari per soddisfare l’espressione regolare.
Capire la differenza tra questi due comportamenti è fondamentale quando si lavora con espressioni regolari, specialmente in casi in cui il testo contiene pattern ripetuti o nidificati, come nei documenti HTML o XML.
Ulteriori esempi di quantificatori non greedy
Supponiamo di avere la seguente stringa:
testo = "Inizio <tag1> contenuto <tag2> fine"
Utilizzando un quantificatore greedy:
match = re.search(r'<.*>', testo) print(match.group()) # Output: <tag1> contenuto <tag2>
Il match include tutto dal primo <
all’ultimo >
prima della parola “fine”. Se invece utilizziamo un quantificatore non greedy:
match = re.search(r'<.*?>', testo) print(match.group()) # Output: <tag1>
Ora, il match si ferma al primo </>
, catturando solo <tag1>
.
Quando utilizzare i quantificatori non greedy
I quantificatori non greedy sono particolarmente utili quando si desidera:
- Estrarre elementi specifici da un testo senza includere contenuti aggiuntivi.
- Evitare che l’espressione regolare catturi più di quanto necessario, soprattutto in presenza di pattern ripetuti o nidificati.
- Analizzare linguaggi di markup come HTML o XML, dove i tag possono essere annidati.
Nota: L’uso corretto dei quantificatori migliora l’efficienza delle espressioni regolari e riduce il rischio di risultati imprevisti.
Uso di lookahead per validare una password che deve contenere almeno una cifra e un carattere speciale:
password = "Password123!" pattern = r'^(?=.*\d)(?=.*[@$!%*?&]).{8,}$' if re.match(pattern, password): print("Password valida") else: print("Password non valida")
Esercizi pratici sulla manipolazione avanzata delle stringhe
Per rafforzare le competenze acquisite, è essenziale svolgere esercizi pratici che mettano in luce tecniche sia teoriche che applicative.
Esercizio 1: Validazione di indirizzi email
Crea una funzione che verifichi se una stringa è un indirizzo email valido utilizzando espressioni regolari.
import re def email_valida(email): pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$' return re.match(pattern, email) is not None # Test print(email_valida("esempio@example.com")) # Output: True print(email_valida("esempio@com")) # Output: False
Esercizio 2: Parsing di file CSV
Leggi un file CSV e utilizza i metodi di manipolazione delle stringhe per estrarre e formattare i dati.
with open('dati.csv', 'r') as file: for linea in file: campi = linea.strip().split(',') print(campi)
Esercizio 3: Serializzazione e Deserializzazione JSON
Utilizza il modulo json
per convertire un dizionario Python in una stringa JSON e viceversa.
import json # Serializzazione dati = {'nome': 'Alice', 'eta': 30, 'citta': 'Roma'} json_string = json.dumps(dati) print(json_string) # Output: {"nome": "Alice", "eta": 30, "citta": "Roma"} # Deserializzazione dati_caricati = json.loads(json_string) print(dati_caricati['nome']) # Output: Alice
Sono amante della tecnologia e delle tante sfumature del mondo IT, ho partecipato, sin dai primi anni di università ad importanti progetti in ambito Internet proseguendo, negli anni, allo startup, sviluppo e direzione di diverse aziende; Nei primi anni di carriera ho lavorato come consulente nel mondo dell’IT italiano, partecipando attivamente a progetti nazionali ed internazionali per realtà quali Ericsson, Telecom, Tin.it, Accenture, Tiscali, CNR. Dal 2010 mi occupo di startup mediante una delle mie società techintouch S.r.l che grazie alla collaborazione con la Digital Magics SpA, di cui sono Partner la Campania, mi occupo di supportare ed accelerare aziende del territorio .
Attualmente ricopro le cariche di :
– CTO MareGroup
– CTO Innoida
– Co-CEO in Techintouch s.r.l.
– Board member in StepFund GP SA
Manager ed imprenditore dal 2000 sono stato,
CEO e founder di Eclettica S.r.l. , Società specializzata in sviluppo software e System Integration
Partner per la Campania di Digital Magics S.p.A.
CTO e co-founder di Nexsoft S.p.A, società specializzata nella Consulenza di Servizi in ambito Informatico e sviluppo di soluzioni di System Integration, CTO della ITsys S.r.l. Società specializzata nella gestione di sistemi IT per la quale ho partecipato attivamente alla fase di startup.
Sognatore da sempre, curioso di novità ed alla ricerca di “nuovi mondi da esplorare“.