Stringhe 1 - introduzione
Scarica zip esercizi
Le stringhe sono sequenze immutabili di caratteri, e costituiscono uno dei tipi di base di Python. In questo foglio vedremo come manipolarle.
Che fare
scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:
strings
strings1.ipynb
strings1-sol.ipynb
strings2.ipynb
strings2-sol.ipynb
strings3.ipynb
strings3-sol.ipynb
strings4.ipynb
strings4-sol.ipynb
strings5-chal.ipynb
jupman.py
ATTENZIONE: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.
apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook
strings1.ipynb
Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte ESERCIZIO, che ti chiederanno di scrivere dei comandi Python nelle celle successive.
Scorciatoie da tastiera:
Per eseguire il codice Python dentro una cella di Jupyter, premi
Control+Invio
Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi
Shift+Invio
Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi
Alt+Invio
Se per caso il Notebook sembra inchiodato, prova a selezionare
Kernel -> Restart
Creare stringhe
Ci sono diversi modi di definire una stringa.
Doppie virgolette, su una linea
[2]:
a = "la mia prima stringa, in doppie virgolette"
[3]:
print(a)
la mia prima stringa, in doppie virgolette
Virgolette singole, su una linea
Questo modo è equivalente al precedente.
[4]:
b = 'la mia seconda stringa, in virgolette singole'
[5]:
print(b)
la mia seconda stringa, in virgolette singole
Tre doppie virgolette, su più linee
[6]:
c = """la mia terza stringa
in triple doppie virgolette
quindi la posso mettere
su più righe"""
[7]:
print(c)
la mia terza stringa
in triple doppie virgolette
quindi la posso mettere
su più righe
Tre apici, su più linee
[8]:
d = '''la mia quarta stringa,
in tripli apici
può pure essere messa
su più linee
'''
[9]:
print(d)
la mia quarta stringa,
in tripli apici
può pure essere messa
su più linee
Stampare - le celle
Per stampare una stringa possiamo usare la funzione print
:
[10]:
print('ciao')
ciao
Notare che nella stampa non sono riportati gli apici.
Se invece scriviamo direttamente la stringa senza la print
, vedremo gli apici:
[11]:
'ciao'
[11]:
'ciao'
Cosa succede se scriviamo la stringa coi doppi apici?
[12]:
"ciao"
[12]:
'ciao'
Vediamo che di default Jupyter la mostra con gli apici singoli
Lo stesso discorso si applica se assegnamo una stringa a una variabile:
[13]:
x = 'ciao'
[14]:
print(x)
ciao
[15]:
x
[15]:
'ciao'
[16]:
y = "ciao"
[17]:
print(y)
ciao
[18]:
y
[18]:
'ciao'
La stringa vuota
La stringa di lunghezza zero si rappresenta con due doppie virgolette ""
o due apici singoli.
Nota che se anche scriviamo due doppie virgolette, Jupyter la mostra che inizia e finisce con un apice solo:
[19]:
""
[19]:
''
Lo stesso vale se associamo una stringa vuota ad una variabile:
[20]:
x = ""
[21]:
x
[21]:
''
Nota anche che se chiediamo a Jupyter di stampare con la print
, non vedremo nulla:
[22]:
print("")
[23]:
print('')
Stampare più stringhe
Per stampare più stringhe su una linea ci sono diversi modi, cominciamo dal più semplice con la print
[24]:
x = "ciao"
y = "Python"
print(x,y) # nota che nella stampa Python ha inserito uno spazio
ciao Python
Alla print
possiamo aggiungere quanti parametri vogliamo, e possono anche essere mischiati con altri tipi come i numeri:
[25]:
x = "ciao"
y = "Python"
z = 3
print(x,y,z)
ciao Python 3
Lunghezza di una stringa
Per ottenere la lunghezza di una stringa (o in genere di qualunque sequenza), possiamo usare la funzione len
:
[26]:
len("ciao")
[26]:
4
[27]:
len("") # stringa vuota
[27]:
0
[28]:
len('') # stringa vuota
[28]:
0
DOMANDA: Possiamo scrivere una cosa del genere?
"len"("ciao")
[29]:
# scrivi qui
DOMANDA: possiamo scrivere una cosa del genere? Cosa produce? un errore? un numero ? Quale?
len("len('ciao')")
DOMANDA: Cosa otteniamo se scriviamo così:
len(((((("ciao"))))))
un errore
la lunghezza della stringa
qualcos’altro
Contare sequenze di escape: Nota che alcune sequenze particolari dette di escape come per esempio \t
occupano meno spazi di quello che sembra (con len
contano come 1), ma stampate ne occupano addirittura di più di 2 !!
Vediamo un esempio, nel prossimo paragrafo scenderemo nei dettagli:
[30]:
len('a\tb')
[30]:
3
[31]:
print('a\tb')
a b
Stampare - sequenze di escape
Alcune sequenze di caratteri dette sequenze di escape sono speciali perchè invece di mostrare caratteri, forzano la stampa a fare cose particolari come andare a capo o inserire spazi extra. Queste sequenze sono sempre precedute da il carattere di backslash \
:
Descrizione |
Sequenza di escape |
---|---|
Ritorno a capo (linefeed) |
|
Tabulazione (ASCII tab) |
|
Esempio - ritorno a capo
[32]:
print("ciao\nmondo")
ciao
mondo
Notare che il ritorno a capo si verifica SOLO quando stampiamo con print
, se invece immettiamo direttamente la stringa nella cella la vediamo tale e quale:
[33]:
"ciao\nmondo"
[33]:
'ciao\nmondo'
In una stringa si possono mettere quante sequenze si vuole:
[34]:
print("La nebbia a gl'irti colli\npiovigginando sale,\ne sotto il maestrale\nurla e biancheggia il mar;")
La nebbia a gl'irti colli
piovigginando sale,
e sotto il maestrale
urla e biancheggia il mar;
Esempio - tabulazione
[35]:
print("ciao\tmondo")
ciao mondo
[36]:
print("ciao\tmondo\tcon\ttante\ttab")
ciao mondo con tante tab
ESERCIZIO: Visto che le sequenze di escape sono speciali, ci si può chiedere quanto siano lunghe. Usa la funzione len
per stampare la lunghezza delle stringhe. Noti qualcosa di strano?
'ab\ncd'
'ab\tcd'
[37]:
# scrivi il codice qui
ESERCIZIO: Prova a selezionare la sequenza di caratteri stampata nella precedente cella. Cosa ottieni ? Una sequenza di spazi, oppure un carattere singolo di tabulazione? Nota che questo può variare a seconda del programma che ha effettivamente stampato la stringa.
ESERCIZIO: trova UNA SOLA stringa che stampata con print
venga mostrata come la seguente.
Questa è
una
sfida apparentemente semplice
USA SOLO combinazioni di
\t
e\n
NON usare spazi
inizia e concludi la stringa con apice singolo
[38]:
# scrivi qui
Questa è
una
sfida apparentemente semplice
ESERCIZIO: Prova a trovare una stringa che stampata con print
venga mostrata così:
At te
n tis
simame
n
te
USA SOLO combinazioni di
\t
e\n
NON usare nessuno spazio
NON usare tripli apici
[39]:
# scrivi qui
At te
n tis
simame
n
te
Caratteri speciali: Per mettere caratteri speciali come il singolo apice '
o le doppie virgolette "
, dobbiamo creare una cosiddetta sequenza di escape, cioè prima scriviamo il carattere backslash \
e poi lo facciamo seguire dal carattere speciale che ci interessa:
Descrizione |
Sequenza di escape |
Risultato a stampa |
---|---|---|
Apice singolo |
|
|
Doppio apice |
|
|
Backslash |
|
|
Esempio
Stampiamo una stringa contenente un apice singolo '
e una doppia virgoletta "
[40]:
stringa = "Così metto \'apici\' e \"doppie virgolette\" nelle stringhe"
[41]:
print(stringa)
Così metto 'apici' e "doppie virgolette" nelle stringhe
Se una stringa inizia con doppi apici, all’interno possiamo usare liberamente singoli apici, anche senza backslash \
:
[42]:
print("Non c'è problema")
Non c'è problema
Se inizia con singoli apici, possiamo liberamente usare doppie virgolette anche senza backslash \
:
[43]:
print('Così è "se vi pare"')
Così è "se vi pare"
ESERCIZIO: Trova una stringa da stampare con la print
che stampata mostri la sequenza seguente
la stringa DEVE iniziare e finire con singoli apici
'
Questo "genio" delle stringhe vuole /\\/ fregarmi \//\ con esercizi atroci O_o'
[44]:
# scrivi qui
Questo "genio" delle stringhe vuole /\\/ fregarmi \//\ con esercizi atroci O_o'
Encodings
Caratteri ASCII
Quando usi le stringhe nei tuoi programmi quotidiani, tipicamente non hai bisogno di pensare molto a come i caratteri sono fisicamente rappresentati come bit in memoria, ma a volte è importante. La rappresentazione è chiamata encoding e va tenuta in considerazione in particolare quando leggi dati da sorgenti esterne come file e siti web.
L’encoding più usato e famoso è lo ASCII (American Standard Code for Information Interchange), che offre 127 caselle fatte da caratteri stampabili dall’alfabeto inglese (a
-z
, A
-Z
, punteggiatura come .;,!
e caratteri come (
, @
…) e sequenze di controllo (come \t
, \n
)
Vedi caratteri stampabili (Wikipedia)
Codici di controllo ASCII (Wikipedia)
Visto che la tabella originale ASCII manca del supporto per linguaggi non-inglesi (per esempio, non ha le lettere accentate italiane come è
,à
, …), parecchie estensioni sono state sviluppate per supportare altri linguaggi, per esempio vedere la pagina Extended ASCII su Wikipedia.
Caratteri Unicode
Quando abbiamo bisogno di caratteri particolari come ✪ che non sono disponibili sulla tastiera, possiamo guardare i caratteri Unicode. Ce ne sono parecchi, e possiamo spesso usarli in Python 3 semplicemente copia-incollandoli. Per esempio, se vai a questa pagina puoi copia-incollare il carattere ✪. In altri casi potrebbe essere così speciale che non può nemmeno essere
correttamente visualizzato, perciò in questi casi puoi usare una sequenza più complessa nel formato \uxxxx
come questo:
Descrizione |
Sequenza di escape |
Risultato stampato |
---|---|---|
Esempio stella in un cerchio nel formato |
|
✪ |
ESERCIZIO: Cerca su Google Unicode heart e prova a stampare un cuore in Python, sia copia-incollando direttamente il carattere che usando la notazione \uxxxx
[45]:
# scrivi qui
I ♥ Python, con copia e incolla
I ♥ Python, anche in formato \uxxxx
Riferimenti: abbiamo solo menzionato Unicode ma può essere un argomento complesso, se avrai mai a che fare con insiemi di caratteri giapponesi o encodings eterogenei trovi qua un paio di riferimenti che dovresti leggere:
prima parte sull’encoding Unicode dal capitolo Stringhe nel libro Immersione in Python 3 e Immersione in Python - Cap 11 - File, entrambe letture caldamente consigliate.
Le stringhe sono immutabili
Le stringhe sono oggetti immutabili, quindi una volta create non si possono più cambiare. Questo può apparire restrittivo, ma non è poi così tragico, perchè abbiamo comunque a disposizione queste alternative:
generare una nuova stringa a partire da stringhe precedenti
se abbiamo una variabile a cui abbiamo assegnato una stringa, possiamo assegnare un’altra stringa a quella variabile
Proviamo a generare una nuova stringa a partire da precedenti, per esempio concatendone due con l’operatore +
[46]:
x = 'ciao'
[47]:
y = x + 'mondo'
[48]:
x
[48]:
'ciao'
[49]:
y
[49]:
'ciaomondo'
L’operazione +
quando eseguita tra stringhe le attacca creando una NUOVA stringa. Questo significa che l’associazione per x
non è affatto cambiata, l’unica vera modifica osservabile è che abbiamo associato la stringa 'ciaomondo
alla variabile y
. Prova a sincerartene in Python Tutor cliccando ripetutamente sul bottone Next:
[50]:
# ATTENZIONE: per usare la funzione jupman.pytut() di seguito,
# è necessario eseguire prima questa cella con Shift+Invio
# basta eseguirla una volta sola, la trovi presente anche in tutti i fogli nella prima cella
import jupman
[51]:
x = 'ciao'
y = x + 'mondo'
print(x)
print(y)
jupman.pytut()
ciao
ciaomondo
[51]:
Riassegnare variabili
Altre variazioni allo stato della memoria possono essere ottenute riassegnando le variabili, per esempio:
[52]:
x = 'ciao'
[53]:
y = 'mondo'
[54]:
x = y # assegnamo a x la stessa stringa contenuta in y
[55]:
x
[55]:
'mondo'
[56]:
y
[56]:
'mondo'
Se una stringa che è stata creata non risulta assegnata a nessuna variabile, Python si occuperà automaticamente di eliminarla dalla memoria. Nel caso qui sopra, la stringa 'ciao'
in sè non è mai cambiata, semplicemente a un certo punto si è ritrovata non più assegnata ad alcuna variabile, e perciò Python ha provveduto ad eliminarla dalla memoria. Guarda cosa succede in Python Tutor:
[57]:
x = 'ciao'
y = 'mondo'
x = y
jupman.pytut()
[57]:
Riassegnare una variabile a sè stessa
Possiamo chiederci cosa succede quando scriviamo qualcosa del genere:
[58]:
x = 'ciao'
x = x
[59]:
print(x)
ciao
Non è successo molto, l’assegnazione di x
è rimasta inalterata.
Ma cosa succede se a destra dell’=
mettiamo una formula più complessa?
[60]:
x = 'ciao'
x = x + 'mondo'
print(x)
ciaomondo
Cerchiamo di capire bene che è successo.
Nella prima linea, Python ha generato la stringa 'ciao'
e l’ha assegnata alla variabile x
. Ma fin qui, niente di straordinario.
Poi, nella seconda linea, Python ha fatto due cose:
ha calcolato il risultato dell’espressione
x + 'mondo'
, generando una NUOVA stringaciaomondo
ha assegnato la stringa appena generata
ciaomondo
alla variabilex
E’ fondamentale capire bene che in presenza di riassegnamenti avvengono i due passaggi appena citati, che quindi ribadiamo:
PRIMA viene calcolato il risultato dell’espressione a destra dell’
=
(avendo quindi a disposizione il vecchio valore associato ax
)POI il risultato viene associato alla variabile a sinistra dell’
=
.
Se proviamo a guardare in Python Tutor, questo doppio passaggio viene eseguito in un colpo solo:
[61]:
x = 'ciao'
x = x + 'mondo'
jupman.pytut()
[61]:
ESERCIZIO: Scrivi del codice che cambia lo stato della memoria in modo che alla fine risulti la stampa seguente:
z = Questo
w = era
x = un problema
y = era
s = Questo era un problema
per scrivere il codice, USA SOLO i simboli
=
,+
,z
,w
,x
,y
,s
E NIENT’ALTROpuoi usare quante linee di codice ritieni opportune
puoi usare ogni simbolo quante volte vuoi
[62]:
# queste variabili ti sono date
z = "Questo"
w = 'è'
x = 'un problema'
y = 'era'
s = ' '
# scrivi qui il codice
[63]:
print("z = ", z)
print("w = ", w)
print("x = ", x)
print("y = ", y)
print("s = ", s)
Stringhe e numeri
Le stringhe in Python hanno il tipo str
:
[64]:
type("ciao mondo")
[64]:
str
Nelle stringhe possiamo inserire dei caratteri che rappresentano cifre:
[65]:
print("Il carattere 5 rappresenta la cifra cinque, il carattere 3 rappresenta la cifra tre")
Il carattere 5 rappresenta la cifra cinque, il carattere 3 rappresenta la cifra tre
Ovviamente possiamo anche costruire una sequenza di cifre, per avere ciò che sembra un numero:
[66]:
print("La sequenza di caratteri 7583 rappresenta il numero settemila cinquecento ottanta tre")
La sequenza di caratteri 7583 rappresenta il numero settemila cinquecento ottanta tre
Detto ciò, possiamo domandarci come si comporta Python quando abbiamo una stringa che contiene solo una sequenza di caratteri che rappresenta un numero, come per esempio '254'
Possiamo usare '254'
(che abbiamo scritto come se fosse una stringa) anche come se fosse un numero? Per esempio, possiamo sommarci 3 ?
'254' + 3
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-29-d39aa62a7e3d> in <module>
----> 1 "254" + 3
TypeError: can only concatenate str (not "int") to str
Come vedi, Python is offende immediatamente, perchè stiamo cercando di mischiare tipi differenti
QUINDI:
Scrivendo
'254'
tra doppi apici creiamo una stringa di tipostr
scrivendo
254
creiamo un numero di tipoint
[67]:
type('254')
[67]:
str
[68]:
type(254)
[68]:
int
ATTENZIONE ALLA print
!!
Se provi a stampare una stringa che contiene solo cifre, Python la mostrerà senza apici, e questo potrebbe ingannarti riguardo la sua vera natura !!
[69]:
print('254')
254
[70]:
print(254)
254
Solo in Jupyter, per mostrare costanti, variabili o risultati di calcoli, come alternativa alla print
puoi immettere direttamente una formula nella cella. In questo caso siamo semplicmente mostrando una costante, e quando è una stringa vedrai degli apici:
[71]:
'254'
[71]:
'254'
[72]:
254
[72]:
254
Lo stesso discorso vale anche per le variabili:
[73]:
x = '254'
[74]:
x
[74]:
'254'
[75]:
y = 254
[76]:
y
[76]:
254
Quindi, solo in Jupyter, quando devi mostrare una costante, una variabile o un calcolo spesso conviene scriverlo direttamente nella cella senza usare la print
.
Conversioni - da stringa a numero
Torniamo al problema di sommare '254' + 3
. La prima è una stringa, il secondo un numero. Se fossero entrambi numeri la somma sicuramente funzionerebbe:
[77]:
254 + 3
[77]:
257
Quindi possiamo provare a convertire la stringa '254'
in un vero intero. Per farlo, possiamo usare int
come se fosse una funzione, e passarci come argomento la stringa da convertire:
[78]:
int('254') + 3
[78]:
257
ATTENZIONE: le stringhe e i numeri sono immutabili !!
Questo significa che scrivendo int('254')
viene generato un nuovo numero senza intaccare minimamente la stringa '254'
da cui si è partiti. Vediamo meglio con un esempio:
[79]:
x = '254' # assegnamo alla variabile x la stringa '254'
[80]:
y = int(x) # assegnamo alla variabile y il numero ottenuto convertendo '254' in int
[81]:
x # la variabile x risulta sempre assegnata alla stringa '254'
[81]:
'254'
[82]:
y # in y invece adesso c'è un numero (notare che qua non abbiamo apici)
[82]:
254
Può essere utile rivedere l’esempio in Python tutor:
[83]:
x = "254"
y = int(x)
print(y + 3)
jupman.pytut()
257
[83]:
ESERCIZIO: Prova a convertire una stringa che rappresenta un numero malformato (per es un numero con dentro un carattere: '43K12'
) in un int
. Che succede?
[84]:
# scrivi qui
Conversioni - da numero a stringa
Un qualsiasi oggetto può essere convertito a stringa usando str
come se fosse una funzione e passandogli l’oggetto da convertire. Proviamo quindi a convertire un numero a stringa:
[85]:
str(5)
[85]:
'5'
notare gli apici nel risultato, che testimoniano che abbiamo effettivamente ottenuto una stringa.
Se per caso vogliamo ottenere una stringa che è la concatenzione di oggetti di tipo diverso dobbiamo stare attenti:
x = 5
s = 'I giorni di lavoro settimanali sono ' + x
print(s)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-154-5951bd3aa528> in <module>
1 x = 5
----> 2 s = 'I giorni di lavoro settimanali sono ' + x
3 print(s)
TypeError: can only concatenate str (not "int") to str
Un modo di ovviare al problema (anche se non il più comodo) è convertire a stringa ciascuno degli oggetti che usiamo nella concatenazione:
[86]:
x = 3
y = 1.6
s = 'questa settimana ho fatto jogging ' + str(x) + ' volte correndo a una media di ' + str(y) + 'km/h'
print(s)
questa settimana ho fatto jogging 3 volte correndo a una media di 1.6km/h
DOMANDA: Visto quanto detto in precedenza, dopo l’esecuzione del codice nella cella precedente, alla variabile x
risulterà associato un numero oppure una stringa ?
Se hai dubbi, usa Python Tutor.
Mostra rispostaFormattare stringhe
Concatenare stringhe con un segno +
come sopra è macchinoso e si presta ad errori. Ci sono diverse soluzioni migliori, ne vedremo un paio - per una recensione completa ci riferiamo al sito Real Python.
Formattare con %
Vediamo come formattare stringhe con l’operatore %
. Per quanto non sia la soluzione più comoda, è comunque molto usata e supportata in tutte le versioni di Python, perciò l’abbiamo adottata nel libro:
[87]:
x = 3
"Ho saltato %s volte" % x
[87]:
'Ho saltato 3 volte'
Nota che abbiamo messo un cosìdetto place-holder (segnaposto) %s
dentro la stringa, per dire a Python di sostituirlo con una variabile. Per passare a Python la variabile, dopo la stringa abbiamo messo un simbolo %
seguito da una variabile, in questo caso x
.
Se vogliamo mettere più di una variabile, dobbiamo solo aggiungere più segnaposti %s
e dopo il %
esterno mettiamo le variabili richieste in parentesi tonde, separandole con virgole:
[88]:
x = 3
y = 5
"Ho saltato %s volte e fatto %s flessioni" % (x,y)
[88]:
'Ho saltato 3 volte e fatto 5 flessioni'
Possiamo mettere quante variabili vogliamo, anche non-numeriche:
[89]:
x = 3
y = 5
premio = 'Migliore Atleta della Valle'
"Ho saltato %s volte, fatto %s flessioni e vinto il premio '%s'" % (x,y,premio)
[89]:
"Ho saltato 3 volte, fatto 5 flessioni e vinto il premio 'Migliore Atleta della Valle'"
Formattare con le f-strings
Le f-strings permettono di inserire direttamente delle espressioni racchiuse tra graffe {}
dentro la stringa. Per segnalare a Python di calcolare e convertire le espressioni in stringhe, la stringa deve essere preceduta dalla lettera f
. Nota che nel momento in cui aggiungi la f
il tuo editor dovrebbe mostrare le espressioni tra graffe di colore diverso.
Attenzione: le f-strings sono solo disponibili da Python \(\geq\) 3.6
[90]:
titolo = "re di Gran Bretagna"
inizio = 1760
fine = 1801
s1 = f"Giorgio III è stato {titolo.upper()} dal {inizio} al {fine}."
print(s1)
s2 = f"Ha governato per {fine - inizio} anni."
print(s2)
Giorgio III è stato RE DI GRAN BRETAGNA dal 1760 al 1801.
Ha governato per 41 anni.
Esercizio - supercar
Hai ricevuto dei soldi, perciò decidi di comprare due modelli di auto sportive. Visto lo stile di guida scellerato prevedi già incidenti, perciò per ciascun modello comprerai tante auto quanti caratteri ci sono nel nome di ciascun modello.
Scrivi del codice che salva il numero di auto che comprerai nelle stringhe:
sa
formattata con i segnaposto%s
sb
formattata come f-string
Esempio - dati:
auto1 = 'Jaguar'
auto2 = 'Ferrari'
Dopo il tuo codice, dovrebbe mostrare:
>>> sa
'Comprerò 6 Jaguar e 7 Ferrari perchè tengo i dindi'
>>> sb
'Comprerò 6 Jaguar e 7 Ferrari perchè tengo i dindi'
[91]:
auto1, auto2 = 'Jaguar','Ferrari' # Comprerò 6 Jaguar e 7 Ferrari perchè tengo i dindi
#auto1, auto2 = 'Porsche','Lamborghini' # Comprerò 7 Porsche e 11 Lamborghini perchè tengo i dindi
# scrivi qui
Prosegui
Trovi ulteriori esercizi nel foglio Stringhe 2 - operatori