Stringhe 1 - introduzione

Scarica zip esercizi

Naviga file online

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")
Mostra rispostaMostra soluzione
[29]:
# scrivi qui


DOMANDA: possiamo scrivere una cosa del genere? Cosa produce? un errore? un numero ? Quale?

len("len('ciao')")
Mostra risposta

DOMANDA: Cosa otteniamo se scriviamo così:

len(((((("ciao"))))))
  1. un errore

  2. la lunghezza della stringa

  3. qualcos’altro

Mostra risposta

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)

\n

Tabulazione (ASCII tab)

\t

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

Mostra soluzione
[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

Mostra soluzione
[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'
Mostra soluzione
[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)

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 \uxxxx

\u272A

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

Mostra soluzione
[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:

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]:
Python Tutor visualization

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]:
Python Tutor visualization

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:

  1. ha calcolato il risultato dell’espressione x + 'mondo', generando una NUOVA stringa ciaomondo

  2. ha assegnato la stringa appena generata ciaomondo alla variabile x

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 a x)

  • 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]:
Python Tutor visualization

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’ALTRO

  • puoi usare quante linee di codice ritieni opportune

  • puoi usare ogni simbolo quante volte vuoi

Mostra soluzione
[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 tipo str

  • scrivendo 254 creiamo un numero di tipo int

[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]:
Python Tutor visualization

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 risposta

Formattare 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'
Mostra soluzione
[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