5. Lavorare con il testo usando le stringhe
Il testo è ovunque nella programmazione. Dalla visualizzazione di messaggi agli utenti, all'elaborazione di file di dati, fino alla creazione di applicazioni web, lavorare con il testo è una delle competenze più fondamentali che svilupperai come programmatore. In Python, lavoriamo con il testo usando le stringhe (strings) — sequenze di caratteri che possono rappresentare parole, frasi o qualsiasi tipo di dato testuale.
Hai già incontrato brevemente le stringhe nei capitoli precedenti quando usavi print() e input(). Ora esploreremo le stringhe in profondità, imparando come crearle, manipolarle e usare le potenti funzionalità integrate di Python sulle stringhe per risolvere problemi reali di elaborazione del testo.
In questo capitolo imparerai come creare stringhe con caratteri speciali, combinare stringhe tra loro, estrarre parti specifiche di stringhe, cambiarne il maiuscolo/minuscolo e la formattazione, cercare del testo all'interno delle stringhe e capire perché le stringhe si comportano in modo diverso dai numeri quando si tratta di modificarle. Alla fine avrai solide basi per lavorare con il testo in Python.
5.1) Letterali di stringa e sequenze di escape
5.1.1) Creare letterali di stringa
Un letterale di stringa (string literal) è un valore stringa scritto direttamente nel tuo codice. Hai già visto stringhe create con apici singoli (') o doppi ("):
# string_basics.py
greeting = 'Hello, World!'
message = "Python is great!"
print(greeting) # Output: Hello, World!
print(message) # Output: Python is great!Sia gli apici singoli sia quelli doppi funzionano in modo identico in Python — la scelta spetta a te. Tuttavia, avere entrambe le opzioni è utile quando la tua stringa contiene al suo interno dei caratteri di apice:
# quotes_in_strings.py
# Usare doppi apici quando la stringa contiene un apice singolo
sentence = "It's a beautiful day!"
print(sentence) # Output: It's a beautiful day!
# Usare apici singoli quando la stringa contiene doppi apici
quote = 'She said, "Hello!"'
print(quote) # Output: She said, "Hello!"Se hai bisogno di includere lo stesso tipo di apice che delimita la tua stringa, puoi farlo eseguire il “escape” con una barra rovesciata (\):
# escaping_quotes.py
# Fare l'escape di un apice singolo dentro una stringa delimitata da apici singoli
sentence = 'It\'s a beautiful day!'
print(sentence) # Output: It's a beautiful day!
# Fare l'escape di doppi apici dentro una stringa delimitata da doppi apici
quote = "She said, \"Hello!\""
print(quote) # Output: She said, "Hello!"La barra rovesciata dice a Python che l'apice successivo fa parte del contenuto della stringa, non la fine della stringa.
5.1.2) Stringhe multilinea con tripli apici
Per le stringhe che si estendono su più righe, Python fornisce i tripli apici (triple quotes) — tre apici singoli (''') o tre doppi apici ("""):
# multiline_strings.py
poem = """Roses are red,
Violets are blue,
Python is awesome,
And so are you!"""
print(poem)
# Output:
# Roses are red,
# Violets are blue,
# Python is awesome,
# And so are you!Le stringhe con tripli apici preservano tutte le interruzioni di riga e gli spazi esattamente come li digiti. Sono particolarmente utili per blocchi di testo lunghi, stringhe di documentazione (le vedremo nel Capitolo 19), o quando hai bisogno di includere sia apici singoli che doppi senza fare l'escape:
# triple_quotes_convenience.py
dialogue = '''The teacher said, "Don't forget: it's important to practice!"'''
print(dialogue) # Output: The teacher said, "Don't forget: it's important to practice!"5.1.3) Sequenze di escape comuni
Oltre a fare l'escape degli apici, la barra rovesciata introduce le sequenze di escape (escape sequences) — combinazioni speciali di due caratteri che rappresentano caratteri difficili o impossibili da digitare direttamente:
# escape_sequences.py
# Newline: va a capo sulla riga successiva
print("First line\nSecond line")
# Output:
# First line
# Second line
# Tab: inserisce una spaziatura orizzontale
print("Name:\tJohn\nAge:\t25")
# Output:
# Name: John
# Age: 25
# Backslash: per includere una barra rovesciata letterale
path = "C:\\Users\\Documents"
print(path) # Output: C:\Users\DocumentsEcco le sequenze di escape più usate:
| Escape Sequence | Significato | Esempio di output |
|---|---|---|
\n | Newline (a capo) | Due righe |
\t | Tab (spaziatura orizzontale) | Testo indentato |
\\ | Backslash | carattere \ |
\' | Apice singolo | carattere ' |
\" | Doppio apice | carattere " |
Capire le sequenze di escape è fondamentale quando lavori con percorsi di file (specialmente su Windows, che usa le barre rovesciate), output formattato o qualsiasi testo che richieda una formattazione speciale.
5.1.4) Stringhe raw per barre rovesciate letterali
A volte vuoi che le barre rovesciate vengano trattate letteralmente, senza attivare le sequenze di escape. Questo è comune quando si lavora con percorsi di file o espressioni regolari (che vedremo brevemente nel Capitolo 39). Python fornisce le stringhe raw (raw strings) anteponendo alla stringa la lettera r:
# raw_strings.py
# Stringa normale: le barre rovesciate attivano le sequenze di escape
regular = "C:\new\test"
print(regular) # Output: C:
# ew est
# (\n diventa newline, \t diventa tab)
# Stringa raw: le barre rovesciate sono letterali
raw = r"C:\new\test"
print(raw) # Output: C:\new\testIn una stringa raw, \n è letteralmente i due caratteri barra rovesciata e n, non un a capo. Le stringhe raw sono particolarmente utili per i percorsi di file di Windows:
# windows_paths.py
# Senza stringa raw, devi fare l'escape di ogni barra rovesciata
path1 = "C:\\Users\\John\\Documents\\file.txt"
# Con una stringa raw, le barre rovesciate funzionano naturalmente
path2 = r"C:\Users\John\Documents\file.txt"
print(path1) # Output: C:\Users\John\Documents\file.txt
print(path2) # Output: C:\Users\John\Documents\file.txtEntrambi gli approcci producono lo stesso risultato, ma le stringhe raw sono più leggibili quando hai molte barre rovesciate.
5.2) Concatenazione e ripetizione di stringhe
5.2.1) Concatenare stringhe con +
Puoi combinare stringhe tra loro usando l'operatore +, chiamato concatenazione (concatenation):
# string_concatenation.py
first_name = "John"
last_name = "Smith"
# Combinare stringhe con +
full_name = first_name + " " + last_name
print(full_name) # Output: John Smith
# Costruire stringhe più lunghe
greeting = "Hello, " + full_name + "!"
print(greeting) # Output: Hello, John Smith!La concatenazione crea una nuova stringa affiancando le stringhe una dopo l'altra. Nota che Python non aggiunge gli spazi automaticamente — devi includerli esplicitamente:
# concatenation_spacing.py
word1 = "Hello"
word2 = "World"
# Senza spazio
no_space = word1 + word2
print(no_space) # Output: HelloWorld
# Con spazio
with_space = word1 + " " + word2
print(with_space) # Output: Hello WorldPuoi concatenare quante stringhe vuoi in una singola espressione:
# multiple_concatenation.py
address = "123" + " " + "Main" + " " + "Street"
print(address) # Output: 123 Main StreetLimitazione importante: puoi concatenare solo stringhe con altre stringhe. Cercare di concatenare una stringa con un numero causerà un errore:
# concatenation_error.py
age = 25
# Questo causerà un errore:
# message = "I am " + age + " years old" # TypeError!
# Devi prima convertire il numero in una stringa
message = "I am " + str(age) + " years old"
print(message) # Output: I am 25 years oldEsploreremo la conversione tra stringhe e numeri più in dettaglio nella Sezione 5.6.
5.2.2) Ripetere stringhe con *
Python fornisce un modo comodo per ripetere una stringa più volte usando l'operatore *:
# string_repetition.py
separator = "-" * 20
print(separator) # Output: --------------------
# Creare pattern
pattern = "abc" * 3
print(pattern) # Output: abcabcabc
# Utile per formattare l'output
print("=" * 30)
print("Important Message")
print("=" * 30)
# Output:
# ==============================
# Important Message
# ==============================L'operatore di ripetizione funziona con qualsiasi intero positivo:
# repetition_examples.py
# Ripetere zero volte restituisce una stringa vuota
nothing = "Hello" * 0
print(nothing) # Output: (empty string)
print(len(nothing)) # Output: 0
# Ripetere una volta restituisce la stringa originale
once = "Hello" * 1
print(once) # Output: Hello
# Ripetizioni più grandi
many = "Go! " * 5
print(many) # Output: Go! Go! Go! Go! Go!La ripetizione di stringhe è particolarmente utile per creare separatori visivi, padding o generare dati di test:
# practical_repetition.py
# Creare una semplice cornice di testo
width = 40
border = "=" * width
title = "Welcome"
padding = " " * ((width - len(title)) // 2)
print(border)
print(padding + title)
print(border)
# Output:
# ========================================
# Welcome
# ========================================5.2.3) Combinare concatenazione e ripetizione
Puoi combinare entrambi gli operatori nella stessa espressione, seguendo le regole di precedenza degli operatori di Python (la moltiplicazione prima dell'addizione, proprio come con i numeri):
# combined_operations.py
# La ripetizione avviene per prima, poi la concatenazione
result = "=" * 10 + " Title " + "=" * 10
print(result) # Output: ========== Title ==========
# Usare le parentesi per controllare l'ordine
repeated_phrase = ("Hello " + "World ") * 3
print(repeated_phrase) # Output: Hello World Hello World Hello WorldQueste operazioni costituiscono le basi della manipolazione delle stringhe, permettendoti di costruire stringhe complesse a partire da pezzi semplici.
5.3) Indicizzazione e slicing delle stringhe
Le stringhe in Python sono sequenze di caratteri, il che significa che ogni carattere ha una posizione specifica. Puoi accedere a singoli caratteri o estrarre porzioni di una stringa usando indicizzazione e slicing.
5.3.1) Comprendere gli indici di stringa
Ogni carattere in una stringa ha una posizione numerica chiamata indice (index). Python usa l'indicizzazione a base zero (zero-based indexing), il che significa che il primo carattere è all'indice 0, il secondo all'indice 1, e così via:
# string_indexing.py
text = "Python"
# Accedere a singoli caratteri tramite indice
print(text[0]) # Output: P (primo carattere)
print(text[1]) # Output: y (secondo carattere)
print(text[5]) # Output: n (sesto carattere)Ecco una rappresentazione visiva di come gli indici corrispondono ai caratteri:
String: P y t h o n
Index: 0 1 2 3 4 5Python supporta anche gli indici negativi, che contano dalla fine della stringa. L'indice -1 si riferisce all'ultimo carattere, -2 al penultimo, e così via:
# negative_indexing.py
text = "Python"
print(text[-1]) # Output: n (ultimo carattere)
print(text[-2]) # Output: o (penultimo)
print(text[-6]) # Output: P (primo carattere)Gli indici negativi sono particolarmente utili quando vuoi accedere a caratteri vicini alla fine di una stringa senza conoscerne la lunghezza esatta:
String: P y t h o n
Positive: 0 1 2 3 4 5
Negative: -6 -5 -4 -3 -2 -1Importante: cercare di accedere a un indice che non esiste causerà un IndexError:
# index_error.py
text = "Python"
# Questo funziona senza problemi
print(text[5]) # Output: n
# Questo causa un errore perché l'indice 6 non esiste
# print(text[6]) # IndexError: string index out of range5.3.2) Slicing delle stringhe per estrarre sottostringhe
Mentre l'indicizzazione ti dà un singolo carattere, lo slicing ti permette di estrarre una porzione di una stringa (chiamata sottostringa (substring)). La sintassi di base è:
string[start:stop]Questo estrae i caratteri dall'indice start fino a (ma escludendo) l'indice stop:
# basic_slicing.py
text = "Python Programming"
# Estrai i caratteri dall'indice 0 fino a (ma escludendo) 6
print(text[0:6]) # Output: Python
# Estrai i caratteri dall'indice 7 fino a 18
print(text[7:18]) # Output: Programming
# Estrai una porzione centrale
print(text[7:11]) # Output: ProgLa cosa fondamentale da ricordare è che l'indice stop non è incluso nel risultato. Pensa agli indici come a posizioni tra i caratteri:
P y t h o n
0 1 2 3 4 5 6Quindi text[0:6] significa "inizia alla posizione 0 e fermati prima della posizione 6", ottenendo i caratteri alle posizioni 0, 1, 2, 3, 4 e 5.
5.3.3) Omettere indici start o stop
Puoi omettere l'indice start per fare slicing dall'inizio, o omettere l'indice stop per fare slicing fino alla fine:
# omitting_indices.py
text = "Python Programming"
# Dall'inizio fino all'indice 6
print(text[:6]) # Output: Python
# Dall'indice 7 fino alla fine
print(text[7:]) # Output: Programming
# L'intera stringa (dall'inizio alla fine)
print(text[:]) # Output: Python ProgrammingQueste scorciatoie sono molto comuni nel codice Python perché rendono chiare le intenzioni ed evitano di scrivere a mano le lunghezze.
5.3.4) Usare indici negativi negli slice
Gli indici negativi funzionano anche negli slice, permettendoti di contare dalla fine:
# negative_slice_indices.py
text = "Python Programming"
# Ultimi 11 caratteri
print(text[-11:]) # Output: Programming
# Tutto tranne gli ultimi 11 caratteri
print(text[:-11]) # Output: Python
# Ultimi 7 caratteri
print(text[-7:]) # Output: ramming
# Dall'indice 7 al terzultimo carattere
print(text[7:-3]) # Output: Programm (si ferma prima di 'ing')Gli indici negativi sono particolarmente utili quando vuoi escludere un certo numero di caratteri dalla fine:
# removing_suffix.py
filename = "document.txt"
# Ottieni tutto tranne gli ultimi 4 caratteri (.txt)
name_without_extension = filename[:-4]
print(name_without_extension) # Output: document5.3.5) Slicing con un valore di passo
Gli slice possono includere un terzo valore chiamato step (passo), che determina di quanti caratteri saltare:
string[start:stop:step]# slicing_with_step.py
text = "Python Programming"
# Un carattere ogni due sull'intera stringa
print(text[::2]) # Output: Pto rgamn
# Un carattere ogni due dall'indice 0 a 6
print(text[0:6:2]) # Output: Pto
# Un carattere ogni tre
print(text[::3]) # Output: Ph oaiUn trucco particolarmente utile è usare un passo di -1 per invertire una stringa:
# reversing_strings.py
text = "Python"
# Inverti l'intera stringa
reversed_text = text[::-1]
print(reversed_text) # Output: nohtyP
# Esempio pratico: controllo dei palindromi
word = "radar"
if word == word[::-1]:
print(f"{word} is a palindrome!") # Output: radar is a palindrome!5.3.6) Lo slicing non causa mai errori
Diversamente dall'indicizzazione, lo slicing è molto tollerante. Se specifichi indici fuori dall'intervallo, Python li aggiusta semplicemente per adattarli:
# safe_slicing.py
text = "Python"
# Tutti questi funzionano senza errori
print(text[0:100]) # Output: Python (si ferma alla fine)
print(text[10:20]) # Output: (empty string - l'inizio è oltre la fine)
print(text[-100:3]) # Output: Pyt (l'inizio è aggiustato a 0)Questo comportamento rende lo slicing sicuro da usare anche quando non conosci esattamente la lunghezza della stringa.
5.3.7) Esempi pratici di slicing
Ecco alcuni pattern comuni che userai spesso:
# practical_slicing.py
text = "Hello, World!"
# Primi 5 caratteri
print(text[:5]) # Output: Hello
# Ultimi 6 caratteri
print(text[-6:]) # Output: World!
# Tutto tranne il primo e l'ultimo carattere
print(text[1:-1]) # Output: ello, World
# Un carattere ogni due
print(text[::2]) # Output: Hlo ol!
# Inverti la stringa
print(text[::-1]) # Output: !dlroW ,olleHCapire indicizzazione e slicing è fondamentale per l'elaborazione del testo in Python. Queste tecniche ricorreranno continuamente in tutto il tuo percorso di programmazione.
5.4) Metodi comuni delle stringhe per maiuscole/minuscole e spazi bianchi
Le stringhe Python includono molti metodi incorporati — funzioni associate agli oggetti stringa che eseguono operazioni su di essi. In questa sezione esploreremo i metodi per cambiare maiuscole/minuscole e gestire gli spazi bianchi, essenziali per pulire e formattare il testo.
5.4.1) Comprendere i metodi delle stringhe
Un metodo (method) si richiama usando la notazione a punto: string.method_name(). I metodi sono funzioni che appartengono a un tipo specifico di oggetto. Per le stringhe, Python fornisce decine di metodi utili:
# method_basics.py
text = "hello"
# Chiamare un metodo su una stringa
result = text.upper()
print(result) # Output: HELLO
# La stringa originale non è cambiata (vedremo perché nella Sezione 5.8)
print(text) # Output: helloI metodi possono essere concatenati perché ciascun metodo restituisce una nuova stringa:
# method_chaining.py
text = " hello world "
# Concatenare più metodi
result = text.strip().upper().replace("WORLD", "PYTHON")
print(result) # Output: HELLO PYTHON5.4.2) Metodi di conversione del maiuscolo/minuscolo
Python fornisce diversi metodi per cambiare il maiuscolo/minuscolo delle stringhe:
# case_methods.py
text = "Python Programming"
# Convertire in maiuscolo
print(text.upper()) # Output: PYTHON PROGRAMMING
# Convertire in minuscolo
print(text.lower()) # Output: python programming
# Maiuscola la prima lettera, minuscole le altre
print(text.capitalize()) # Output: Python programming
# Title case: maiuscola la prima lettera di ogni parola
print(text.title()) # Output: Python ProgrammingQuesti metodi sono particolarmente utili per standardizzare l'input dell'utente:
# case_normalization.py
# Simulare l'input dell'utente
user_input = "YES"
# Confronto case-insensitive
if user_input.lower() == "yes":
print("User confirmed!") # Output: User confirmed!
# Un altro approccio usando upper()
command = "start"
if command.upper() == "START":
print("Starting process...") # Output: Starting process...Il metodo title() mette in maiuscolo la prima lettera di ogni parola, utile per formattare nomi e titoli:
# title_case.py
name = "john smith"
print(name.title()) # Output: John Smith
book = "the great gatsby"
print(book.title()) # Output: The Great GatsbyTuttavia, attenzione: title() ha dei limiti con gli apostrofi e casi speciali:
# title_limitations.py
text = "it's a beautiful day"
print(text.title()) # Output: It'S A Beautiful Day (nota la S maiuscola)
# Per una gestione più sofisticata del title case, potresti aver bisogno di logica personalizzataIl metodo capitalize() mette in maiuscolo solo il primissimo carattere dell'intera stringa:
# capitalize_examples.py
sentence = "python is great"
print(sentence.capitalize()) # Output: Python is great
# Nota: solo la prima lettera è in maiuscolo
multi_word = "hello world"
print(multi_word.capitalize()) # Output: Hello world (non Hello World)5.4.3) Metodi di controllo del maiuscolo/minuscolo
Python fornisce anche metodi per controllare il maiuscolo/minuscolo delle stringhe:
# case_checking.py
text1 = "HELLO"
text2 = "hello"
text3 = "Hello World"
# Verificare se tutti i caratteri sono maiuscoli
print(text1.isupper()) # Output: True
print(text2.isupper()) # Output: False
# Verificare se tutti i caratteri sono minuscoli
print(text1.islower()) # Output: False
print(text2.islower()) # Output: True
# Verificare se la stringa è in title case
print(text3.istitle()) # Output: True
print(text2.istitle()) # Output: FalseQuesti metodi di controllo restituiscono True o False (valori booleani che abbiamo visto nel Capitolo 3), rendendoli perfetti per le condizioni:
# case_checking_conditions.py
password = "SECRET123"
if password.isupper():
print("Password is all uppercase") # Output: Password is all uppercase5.4.4) Metodi per rimuovere gli spazi bianchi
Gli spazi bianchi (whitespace) includono spazi, tab (\t) e newline (\n). Python fornisce metodi per rimuovere gli spazi bianchi dai bordi delle stringhe:
# whitespace_removal.py
text = " Hello, World! "
# Rimuovere gli spazi bianchi da entrambi i lati
print(text.strip()) # Output: Hello, World!
# Rimuovere gli spazi bianchi da sinistra (inizio)
print(text.lstrip()) # Output: Hello, World!
# Rimuovere gli spazi bianchi da destra (fine)
print(text.rstrip()) # Output: Hello, World!Il metodo strip() è estremamente utile per ripulire l'input dell'utente:
# cleaning_input.py
# Simulare input dell'utente con spazi extra
user_name = " John Smith "
# Ripulire l'input
clean_name = user_name.strip()
print(f"Welcome, {clean_name}!") # Output: Welcome, John Smith!Questi metodi rimuovono anche tab e newline:
# strip_all_whitespace.py
text = "\n\t Hello \t\n"
print(repr(text)) # Output: '\n\t Hello \t\n'
cleaned = text.strip()
print(repr(cleaned)) # Output: 'Hello'Nota che strip(), lstrip() e rstrip() rimuovono solo gli spazi bianchi dai bordi, non dal centro:
# strip_edges_only.py
text = " Hello World "
print(text.strip()) # Output: Hello World (gli spazi in mezzo rimangono)5.4.5) Rimuovere caratteri specifici
I metodi strip possono anche rimuovere caratteri specifici (non solo spazi bianchi) dai bordi:
# Remove multiple different characters
text = "...Hello!!!"
cleaned = text.strip(".!")
print(cleaned) # Output: HelloQuando passi una stringa a strip(), rimuove qualsiasi combinazione di quei caratteri dai bordi:
# strip_character_set.py
text = "xxxyyyHelloyyyxxx"
# Rimuovere eventuali x o y da entrambi i lati
result = text.strip("xy")
print(result) # Output: Hello5.4.6) Esempi pratici che combinano metodi su maiuscole/minuscole e spazi bianchi
Ecco scenari reali in cui questi metodi sono preziosi:
# practical_text_cleaning.py
# Pulire e standardizzare l'input dell'utente
user_email = " JohnSmith@EXAMPLE.com "
clean_email = user_email.strip().lower()
print(clean_email) # Output: johnsmith@example.com
# Formattare correttamente i nomi
raw_name = " john smith "
formatted_name = raw_name.strip().title()
print(formatted_name) # Output: John Smith
# Elaborare comandi (case-insensitive)
command = " START "
if command.strip().upper() == "START":
print("Command recognized!") # Output: Command recognized!Questi metodi costituiscono le basi della pulizia e normalizzazione del testo, che userai continuamente quando elabori input dell'utente, leggi file o prepari i dati per l'analisi.
5.5) Ricerca e sostituzione nelle stringhe
Trovare e modificare testo all'interno delle stringhe è un compito comune in programmazione. Python fornisce metodi potenti per cercare sottostringhe e sostituire testo.
5.5.1) Trovare sottostringhe con find() e index()
Il metodo find() cerca una sottostringa e restituisce l'indice in cui appare per la prima volta:
# find_method.py
text = "Python is great. Python is powerful."
# Trova la prima occorrenza di "Python"
position = text.find("Python")
print(position) # Output: 0 (trovato all'inizio)
# Trova "great"
position = text.find("great")
print(position) # Output: 10
# Trova qualcosa che non esiste
position = text.find("Java")
print(position) # Output: -1 (not found)Il metodo find() restituisce -1 se la sottostringa non viene trovata, il che lo rende sicuro da usare senza causare errori:
# safe_searching.py
text = "Hello, World!"
# Verificare se una sottostringa esiste
if text.find("World") != -1:
print("Found 'World'!") # Output: Found 'World'!
if text.find("Python") == -1:
print("'Python' not found") # Output: 'Python' not foundPuoi anche cercare una sottostringa a partire da una posizione specifica:
# find_with_start.py
text = "Python is great. Python is powerful."
# Trova la prima occorrenza
first = text.find("Python")
print(first) # Output: 0
# Trova la successiva occorrenza dopo la prima
second = text.find("Python", first + 1)
print(second) # Output: 17Il metodo index() funziona in modo simile a find(), ma solleva un errore se la sottostringa non viene trovata:
# index_method.py
text = "Hello, World!"
# Questo funziona senza problemi
position = text.index("World")
print(position) # Output: 7
# Questo causerebbe un ValueError:
# position = text.index("Python") # ValueError: substring not foundQuando usare l'uno o l'altro:
- Usa
find()quando vuoi verificare se qualcosa esiste (restituisce -1 se non trovato) - Usa
index()quando ti aspetti che la sottostringa ci sia (solleva un errore se non trovata)
# choosing_find_vs_index.py
text = "Python Programming"
# Usare find() per un controllo sicuro
if text.find("Java") != -1:
print("Found Java")
else:
print("Java not found") # Output: Java not found
# Usare index() quando sei sicuro che esista
position = text.index("Python") # Sappiamo che Python c'è
print(f"Found at position {position}") # Output: Found at position 05.5.2) Trovare dalla fine con rfind() e rindex()
I metodi rfind() e rindex() cercano a partire da destra (dalla fine) della stringa:
# rfind_method.py
text = "Python is great. Python is powerful."
# Trova l'ultima occorrenza di "Python"
last_position = text.rfind("Python")
print(last_position) # Output: 17
# Confronta con find() che dà la prima occorrenza
first_position = text.find("Python")
print(first_position) # Output: 0Questo è utile quando vuoi l'ultima occorrenza di qualcosa:
# last_occurrence.py
filename = "document.backup.txt"
# Trova l'ultimo punto (per ottenere l'estensione del file)
last_dot = filename.rfind(".")
if last_dot != -1:
extension = filename[last_dot:]
print(extension) # Output: .txt5.5.3) Contare le occorrenze con count()
Il metodo count() ti dice quante volte appare una sottostringa:
# count_method.py
text = "Python is great. Python is powerful. Python is fun."
# Conta quante volte appare "Python"
count = text.count("Python")
print(count) # Output: 3
# Conta una lettera
letter_count = text.count("o")
print(f"Letter 'o' appears {letter_count} times") # Output: Letter 'o' appears 4 timesPuoi anche contare all'interno di un intervallo specifico:
# count_in_range.py
text = "abcabcabc"
# Conta "abc" sull'intera stringa
total = text.count("abc")
print(total) # Output: 3
# Conta "abc" solo nei primi 6 caratteri
partial = text.count("abc", 0, 6)
print(partial) # Output: 25.5.4) Sostituire testo con replace()
Il metodo replace() crea una nuova stringa in cui tutte le occorrenze di una sottostringa sono sostituite:
# replace_method.py
text = "I love Java. Java is great."
# Sostituire tutte le occorrenze di "Java" con "Python"
new_text = text.replace("Java", "Python")
print(new_text) # Output: I love Python. Python is great.
# La stringa originale non è cambiata
print(text) # Output: I love Java. Java is great.Puoi limitare il numero di sostituzioni con un terzo argomento:
# limited_replace.py
text = "one one one one"
# Sostituisci solo le prime 2 occorrenze
result = text.replace("one", "two", 2)
print(result) # Output: two two one oneIl metodo replace() fa distinzione tra maiuscole e minuscole (è case-sensitive):
# case_sensitive_replace.py
text = "Python is great. python is powerful."
# Questo sostituisce solo "Python" (con P maiuscola)
result = text.replace("Python", "Java")
print(result) # Output: Java is great. python is powerful.Per una sostituzione case-insensitive, devi gestirla manualmente:
# case_insensitive_approach.py
text = "Python is great. python is powerful."
# Converti in minuscolo, sostituisci, ma così perdi il maiuscolo/minuscolo originale
result = text.lower().replace("python", "java")
print(result) # Output: java is great. java is powerful.5.5.5) Esempi pratici di ricerca e sostituzione
Ecco scenari reali in cui questi metodi sono molto utili:
# practical_search_replace.py
# Pulizia dei dati: rimuovere caratteri indesiderati
phone = "123-456-7890"
clean_phone = phone.replace("-", "")
print(clean_phone) # Output: 1234567890
# Censurare parole
message = "This is a bad word and another bad word."
censored = message.replace("bad", "***")
print(censored) # Output: This is a *** word and another *** word.
# Estrarre l'estensione di un file
filename = "document.txt"
dot_position = filename.rfind(".")
if dot_position != -1:
extension = filename[dot_position + 1:]
print(f"File type: {extension}") # Output: File type: txt
# Contare le occorrenze di una parola (approccio semplice)
text = "Python is fun. I love Python. Python rocks!"
word = "Python"
occurrences = text.count(word)
print(f"'{word}' appears {occurrences} times") # Output: 'Python' appears 3 timesQuesti metodi di ricerca e sostituzione sono strumenti fondamentali per l'elaborazione del testo, la pulizia dei dati e la manipolazione delle stringhe nei programmi Python.
5.6) Conversione tra stringhe e numeri
Uno dei compiti più comuni in programmazione è convertire fra rappresentazioni testuali e numeriche. Quando leggi input dell'utente con input(), ottieni una stringa — anche se l'utente digita un numero. Allo stesso modo, quando vuoi mostrare numeri in un testo, devi convertirli in stringhe.
5.6.1) Convertire stringhe in numeri
Abbiamo già visto le funzioni int() e float() nel Capitolo 3, ma esploriamole più in dettaglio:
# string_to_number.py
# Convertire una stringa in intero
age_text = "25"
age = int(age_text)
print(age) # Output: 25
print(type(age)) # Output: <class 'int'>
# Convertire una stringa in float
price_text = "19.99"
price = float(price_text)
print(price) # Output: 19.99
print(type(price)) # Output: <class 'float'>Queste conversioni sono essenziali quando elabori input dell'utente:
# user_input_conversion.py
# Simulare l'input dell'utente (nel codice reale useresti input())
user_age = "30"
user_height = "5.9"
# Converti in numeri così possiamo fare operazioni matematiche
age = int(user_age)
height = float(user_height)
# Ora possiamo eseguire calcoli
print(f"In 10 years, you'll be {age + 10}") # Output: In 10 years, you'll be 40
print(f"Your height in meters: {height * 0.3048:.2f}") # Output: Your height in meters: 1.80Importante: la stringa deve rappresentare un numero valido, altrimenti otterrai un errore:
# conversion_errors.py
# Questi funzionano senza problemi
print(int("123")) # Output: 123
print(float("3.14")) # Output: 3.14
# Questi causano ValueError:
# print(int("hello")) # ValueError: invalid literal for int()
# print(int("12.5")) # ValueError: invalid literal for int() with base 10
# print(float("12.5.3")) # ValueError: could not convert string to floatImpareremo come gestire questi errori in modo elegante nel Capitolo 28. Per ora, sappi che la conversione può fallire se la stringa non rappresenta un numero valido.
5.6.2) Gestire gli spazi bianchi nelle stringhe numeriche
Le funzioni di conversione di Python gestiscono automaticamente spazi bianchi iniziali e finali:
# whitespace_handling.py
# Tutti questi funzionano nonostante gli spazi
print(int(" 42 ")) # Output: 42
print(float(" 3.14 ")) # Output: 3.14
# Combinare strip() con la conversione per sicurezza
user_input = " 100 "
number = int(user_input.strip())
print(number) # Output: 100Questo è utile quando elabori input dell'utente, che spesso contengono spazi extra.
5.6.3) Convertire numeri in stringhe
La funzione str() converte qualsiasi valore nella sua rappresentazione come stringa:
# number_to_string.py
age = 25
height = 5.9
# Convertire numeri in stringhe
age_text = str(age)
height_text = str(height)
print(type(age_text)) # Output: <class 'str'>
print(type(height_text)) # Output: <class 'str'>
# Ora possiamo concatenarli con altre stringhe
message = "I am " + str(age) + " years old"
print(message) # Output: I am 25 years oldQuesto è necessario ogni volta che vuoi combinare numeri con stringhe:
# concatenation_with_numbers.py
score = 95
total = 100
# Devi convertire i numeri in stringhe per la concatenazione
result = "Score: " + str(score) + "/" + str(total)
print(result) # Output: Score: 95/100
# Alternativa: usare le f-string (trattate in dettaglio nel Capitolo 6)
result = f"Score: {score}/{total}"
print(result) # Output: Score: 95/1005.6.4) Conversione tra interi e float
Puoi anche convertire tra tipi int e float:
# int_float_conversion.py
# Float in int (tronca la parte decimale)
price = 19.99
price_int = int(price)
print(price_int) # Output: 19 (parte decimale rimossa, non arrotondata)
# Int in float
age = 25
age_float = float(age)
print(age_float) # Output: 25.0Importante: convertire un float in int tronca (taglia) la parte decimale — non arrotonda:
# truncation_not_rounding.py
print(int(3.9)) # Output: 3 (non 4!)
print(int(3.1)) # Output: 3
print(int(-3.9)) # Output: -3 (tronca verso zero)
# Per arrotondare, usa prima la funzione round() (trattata nel Capitolo 4)
print(int(round(3.9))) # Output: 45.6.5) Esempi pratici di conversione
Ecco scenari reali in cui la conversione di tipo è essenziale:
# practical_conversions.py
# Lettura ed elaborazione dell'input dell'utente
# (Simulare input() - nel codice reale useresti input())
user_input = "42"
# Convertire in numero per fare calcoli
number = int(user_input)
doubled = number * 2
print(f"Double of {number} is {doubled}") # Output: Double of 42 is 84
# Costruire output formattato
name = "John"
age = 30
height = 5.9
# Metodo 1: Convertire i numeri in stringhe
info = name + " is " + str(age) + " years old and " + str(height) + " feet tall"
print(info) # Output: John is 30 years old and 5.9 feet tall
# Metodo 2: Usare le f-string (più leggibile - trattato nel Capitolo 6)
info = f"{name} is {age} years old and {height} feet tall"
print(info) # Output: John is 30 years old and 5.9 feet tall
# Elaborare dati da file (anticipazione)
data_line = "100,200,300" # Simulare una riga da un file CSV
numbers = data_line.split(",") # Dividere in una lista di stringhe
total = int(numbers[0]) + int(numbers[1]) + int(numbers[2])
print(f"Total: {total}") # Output: Total: 6005.6.6) Errori comuni nella conversione
Fai attenzione a questi errori frequenti:
# conversion_pitfalls.py
# Problema 1: Cercare di convertire stringhe non numeriche
# text = "hello"
# number = int(text) # ValueError!
# Problema 2: Dimenticare di convertire prima dell'aritmetica
age_text = "25"
# next_year = age_text + 1 # TypeError: can only concatenate str to str
# Approccio corretto:
age = int(age_text)
next_year = age + 1
print(next_year) # Output: 26
# Problema 3: Perdere precisione con int()
price = 19.99
price_int = int(price) # Diventa 19, non 20!
print(price_int) # Output: 19
# Problema 4: Cercare di convertire stringhe con virgole o simboli di valuta
# price_text = "$1,234.56"
# price = float(price_text) # ValueError!
# Devi prima ripulire la stringa:
price_text = "$1,234.56"
clean_price = price_text.replace("$", "").replace(",", "")
price = float(clean_price)
print(price) # Output: 1234.56Capire la conversione di tipo è cruciale per costruire programmi che interagiscono con gli utenti ed elaborano dati reali. Userai continuamente queste conversioni nel tuo percorso di programmazione Python.
5.7) Controllare le sottostringhe con in e not in
Python fornisce modi semplici e leggibili per verificare se una stringa ne contiene un'altra usando gli operatori in e not in. Questi sono estremamente utili per validazione, filtraggio e presa di decisioni nei tuoi programmi.
5.7.1) Usare in per controllare le sottostringhe
L'operatore in restituisce True se una stringa viene trovata all'interno di un'altra, e False altrimenti:
# in_operator.py
text = "Python is a powerful programming language"
# Verificare se una sottostringa esiste
print("Python" in text) # Output: True
print("powerful" in text) # Output: True
print("Java" in text) # Output: FalseQuesto è molto più leggibile rispetto all'uso di find() o index():
# in_vs_find.py
text = "Hello, World!"
# Usare in (chiaro e leggibile)
if "World" in text:
print("Found World!") # Output: Found World!
# Usare find (meno leggibile)
if text.find("World") != -1:
print("Found World!") # Output: Found World!L'operatore in distingue tra maiuscole e minuscole (è case-sensitive):
# case_sensitivity.py
text = "Python Programming"
print("python" in text) # Output: False (p minuscola)
print("Python" in text) # Output: True (P maiuscola)
# Per un controllo case-insensitive, converti prima in minuscolo
print("python" in text.lower()) # Output: True5.7.2) Usare not in per controllare l'assenza
L'operatore not in controlla se una sottostringa NON è presente:
# not_in_operator.py
text = "Python is great"
print("Java" not in text) # Output: True (Java non c'è)
print("Python" not in text) # Output: False (Python c'è)Questo è particolarmente utile per la validazione:
# validation_examples.py
# Controllare la presenza di caratteri non validi in un nome utente
username = "john_smith"
if " " not in username:
print("Username is valid (no spaces)") # Output: Username is valid (no spaces)5.7.3) Metodi aggiuntivi di controllo sulle stringhe
Python fornisce diversi altri metodi utili per controllare le proprietà delle stringhe:
# string_checking_methods.py
text = "Python"
# Verificare se la stringa inizia con una sottostringa
print(text.startswith("Py")) # Output: True
print(text.startswith("Ja")) # Output: False
# Verificare se la stringa termina con una sottostringa
print(text.endswith("on")) # Output: True
print(text.endswith("ing")) # Output: False
# Questi sono più precisi rispetto all'uso di in
filename = "report.txt"
print(filename.endswith(".txt")) # Output: True
print(".txt" in filename) # Output: True (ma meno preciso)
# startswith/endswith possono controllare più opzioni
filename = "document.pdf"
print(filename.endswith((".pdf", ".doc", ".txt"))) # Output: TrueQuesti metodi di controllo sono strumenti essenziali per la validazione dell'input, il filtraggio dei dati e la logica condizionale nei tuoi programmi. Rendono il codice più leggibile e manutenibile rispetto alla ricerca manuale nelle stringhe.
5.8) Le stringhe sono immutabili: cosa significa in pratica
Una delle caratteristiche più importanti delle stringhe Python è che sono immutabili (immutable) — una volta create, non possono essere modificate. Questo può sembrare inizialmente una limitazione, ma capire l'immutabilità è cruciale per scrivere codice Python corretto ed evitare bug sottili.
5.8.1) Cosa significa immutabilità
Quando diciamo che le stringhe sono immutabili, intendiamo che non puoi modificare i caratteri in una stringa esistente. Qualsiasi operazione che sembra "cambiare" una stringa in realtà crea una nuova stringa:
# immutability_basics.py
text = "Hello"
# Questo sembra cambiare la stringa, ma non è così
text = text + " World"
print(text) # Output: Hello World
# Quello che è realmente successo:
# 1. Python ha creato una nuova stringa "Hello World"
# 2. La variabile 'text' ora si riferisce a questa nuova stringa
# 3. La stringa originale "Hello" esiste ancora (finché non viene garbage-collected)Non puoi cambiare singoli caratteri in una stringa:
# cannot_modify_characters.py
text = "Hello"
# Questo causa un errore:
# text[0] = "J" # TypeError: 'str' object does not support item assignment
# Devi invece creare una nuova stringa
text = "J" + text[1:]
print(text) # Output: JelloQuesto è fondamentalmente diverso dal modo in cui funzionano le liste (che vedremo nel Capitolo 13). Le liste sono mutabili — puoi cambiarne gli elementi:
# lists_are_mutable.py
# Anteprima delle liste (trattate nel Capitolo 13)
numbers = [1, 2, 3]
numbers[0] = 10 # Questo funziona senza problemi con le liste
print(numbers) # Output: [10, 2, 3]
# Ma le stringhe non lo permettono:
text = "Hello"
# text[0] = "J" # TypeError con le stringhe!5.8.2) Perché i metodi delle stringhe restituiscono nuove stringhe
Tutti i metodi delle stringhe che sembrano modificare una stringa in realtà restituiscono una nuova stringa, lasciando intatta l'originale:
# methods_return_new_strings.py
original = "hello world"
# Questi metodi restituiscono nuove stringhe
uppercase = original.upper()
capitalized = original.capitalize()
replaced = original.replace("world", "Python")
# La stringa originale non è cambiata
print(original) # Output: hello world
print(uppercase) # Output: HELLO WORLD
print(capitalized) # Output: Hello world
print(replaced) # Output: hello PythonPer questo motivo è necessario assegnare il risultato a una variabile (o usare la stessa variabile) per mantenere le modifiche:
# keeping_changes.py
text = " hello "
# Errato: il risultato va perso
text.strip()
print(text) # Output: hello (ha ancora gli spazi!)
# Corretto: assegnare il risultato
text = text.strip()
print(text) # Output: hello (spazi rimossi)Questo è un errore comune per i principianti:
# common_mistake.py
message = "python programming"
# Errore: chiamare il metodo senza usare il risultato
message.upper()
message.replace("python", "Python")
print(message) # Output: python programming (immutata!)
# Corretto: assegnare i risultati
message = message.upper()
message = message.replace("PYTHON", "Python")
print(message) # Output: Python PROGRAMMING5.8.3) Implicazioni dell'immutabilità
Capire l'immutabilità ti aiuta a scrivere codice migliore:
1. Le stringhe sono sicure da condividere:
# safe_sharing.py
original = "Hello"
copy = original # Entrambe le variabili puntano alla stessa stringa
# Poiché le stringhe sono immutabili, questo è sicuro
copy = copy + " World"
print(original) # Output: Hello (immutata)
print(copy) # Output: Hello World (nuova stringa)2. Le operazioni sulle stringhe creano nuovi oggetti:
# new_objects.py
text = "Python"
# Ogni operazione crea un nuovo oggetto stringa
result1 = text.upper()
result2 = text.lower()
result3 = text.replace("P", "J")
# Tutti oggetti diversi
print(id(text)) # Un indirizzo di memoria
print(id(result1)) # Indirizzo di memoria diverso
print(id(result2)) # Indirizzo di memoria diverso
print(id(result3)) # Indirizzo di memoria diverso3. Costruire stringhe nei loop può essere inefficiente:
# inefficient_string_building.py
# Questo crea molti oggetti stringa temporanei
result = ""
for i in range(5):
result = result + str(i) # Crea una nuova stringa ogni volta
print(result) # Output: 01234
# Approccio più efficiente (per molte concatenazioni):
# Usare una lista e join (lo impareremo nel Capitolo 6)
parts = []
for i in range(5):
parts.append(str(i))
result = "".join(parts)
print(result) # Output: 012345.8.4) Immutabilità e argomenti di funzione
Quando passi una stringa a una funzione, non devi preoccuparti che venga modificata accidentalmente:
# safe_function_arguments.py
def process_text(text):
# Qualsiasi operazione crea nuove stringhe
text = text.upper()
text = text.replace("A", "X")
return text
original = "banana"
result = process_text(original)
print(original) # Output: banana (immutata)
print(result) # Output: BXNXNX (versione modificata)Questo è diverso dai tipi mutabili (come le liste, che vedremo nel Capitolo 13), in cui le modifiche dentro le funzioni influenzano l'oggetto originale.
5.8.5) Visualizzare l'immutabilità
Ecco una rappresentazione visiva di ciò che accade quando "modifichi" una stringa:
Capire che le stringhe sono immutabili ti aiuta a:
- Evitare errori in cui dimentichi di salvare i risultati dei metodi
- Capire perché le operazioni sulle stringhe creano nuovi oggetti
- Scrivere codice più efficiente quando costruisci stringhe grandi
- Condividere in modo sicuro le stringhe tra parti diverse del tuo programma
Questa immutabilità è una caratteristica fondamentale che distingue le stringhe dai tipi mutabili come le liste, che esploreremo in dettaglio nella Parte IV di questo libro.
Riepilogo del capitolo:
In questo capitolo hai imparato le basi per lavorare con il testo in Python usando le stringhe. Ora sai come:
- Creare letterali di stringa usando apici e sequenze di escape
- Combinare stringhe con concatenazione e ripetizione
- Accedere a singoli caratteri ed estrarre sottostringhe con indicizzazione e slicing
- Trasformare le stringhe usando metodi per il maiuscolo/minuscolo e la rimozione degli spazi bianchi
- Cercare e sostituire testo all'interno delle stringhe
- Convertire tra stringhe e numeri per l'elaborazione dell'input e la formattazione dell'output
- Controllare le sottostringhe usando gli operatori
inenot in - Riconoscere che le stringhe sono immutabili e cosa significa questo per il tuo codice
Queste competenze di manipolazione delle stringhe costituiscono le fondamenta dell'elaborazione del testo in Python. Userai queste tecniche continuamente quando costruirai interfacce utente, elaborerai file di dati, validerai input e formatterai l'output.
Nel prossimo capitolo, costruiremo su queste basi esplorando tecniche più avanzate per la gestione delle stringhe, tra cui lo splitting e il joining delle stringhe, la potente formattazione con le f-string e il metodo format(), e la comprensione della codifica del testo per lavorare con caratteri internazionali.