Trovate le slide su slides.poul.org e gli esempi su gitlab.poul.org/corsi/Python
Per aprire un file si utilizza la funzione open()
.
f = open("miofile.txt")
Python supporta due tipi di file: testuali e binari
f1 = open("miofile1.txt", "r") # apertura in lettura
f2 = open("miofile2.txt", "w") # apertura in scrittura dall'inizio
f3 = open("miofile3.txt", "a") # apertura in scrittura dalla fine
I file di testo vengono letti/scritti usando un encoding per rappresentare i caratteri in formato binario in modo trasparente.
Es: nell'encoding utf-8
(default) il carattere A
viene codificato come il byte di valore 0x41
.
Per aprire un file in modalità binaria basta aggiungere b
al secondo parametro di open()
f1 = open("miofile1.bin", "rb") # apertura in lettura
f2 = open("miofile2.bin", "wb") # apertura in scrittura dall'inizio
f3 = open("miofile3.bin", "ab") # apertura in scrittura dalla fine
Il metodo write
di un file testuale accetta stringhe (str
).
f = open("miofile.txt", "w")
f.write("Ciao!\n")
f.close()
!cat miofile.txt
Ciao!
Sui file binari, invece, si scrivono e leggono bytes
.
f = open("miofile.bin", "wb")
f.write(b"\xDE\xAD\xBE\xEF")
f.close()
!cat miofile.bin | xxd
00000000: dead beef ....
f = open("miofile.txt")
letto = f.read()
print("Letti: {} caratteri".format(len(letto)))
print("{}".format(letto))
Letti: 6 caratteri Ciao!
Per leggere un file una riga alla volta possiamo fare così:
f = open("python_zen.txt")
for riga in f:
print("Letta riga:", riga)
--------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) <ipython-input-6-18e975bdb722> in <module> ----> 1 f = open("python_zen.txt") 2 for riga in f: 3 print("Letta riga:", riga) FileNotFoundError: [Errno 2] No such file or directory: 'python_zen.txt'
I file aperti vanno chiusi!
f.close()
Per evitare di dimenticarsi di chiudere un file aperto possiamo usare questo costrutto
with open("python_zen.txt") as f:
contenuto = f.read()
print(contenuto)
Il file viene chiuso automaticamente
# Lista di tutti i numeri fino a 10
numbers = [i for i in range(10)]
numbers
# Lista dei numeri pari fino a 10
evens = [i for i in numbers if i % 2 == 0]
evens
# Lista dei quadrati dei numeri pari fino a 10
squares = [i**2 for i in evens]
squares
In modo analogo possiamo creare dizionari.
# Dizionario dei numeri fino a 10, associati al loro valore al quadrato.
squares = {i: i**2 for i in range(10)}
squares
Insiemi matematici: contengono elementi unici non ordinati.
insieme = set() # crea un insieme vuoto
insieme.add(1)
insieme.add(2)
insieme
insieme = {1, 2} # equivalente a insieme = set([1,2])
insieme.remove(2)
insieme
insieme.add(1) # 1 è già presente, l'insieme rimarrà immutato
insieme
A = {1,2,3,4}
B = {2,4,6,8}
# differenza
A - B
# Unione
A | B
# Intersezione
A & B
È possibile in modo analogo creare anche dei set usando le comprehension
A = {i for i in range(20)} # set dei numeri fino a 20
A
Finora abbiamo visto che esistono diversi tipi di dato: interi, float, stringhe, liste, dizionari, ...
Possiamo ottenere il tipo di una variabile o di un dato usando type
type(1)
type(1.0)
type("ciao")
type([1,"due",3])
stringa = "1"
type(stringa) # le variabili prendono il tipo del dato contenuto
# conversione str -> int
numero = int(stringa)
type(numero)
# Questa conversione solleverà un'eccezione
numero_err = int("ciao")
stringa = "Partecipanti: "
n = 150
#Errato! stringa + numero
stringa + n
# conversione int -> str
stringa + str(n)
Nella pratica per creare stringhe è meglio usare format()
, che gestisce le conversioni
"Partecipanti: {}".format(n)
str
¶"Ciao {}".format("Luca")
"Ciao {surname} {name}".format(name="Luca", surname="Anonimo")
È molto utile per formattare numeri o creare tabelle
1/3
"{:.4}".format(1/3) # Tiene solo 4 cifre decimali
"{:8}".format(123) # Allinea a destra il numero su 8 colonne
numeri = [1 / i for i in range(1, 6)]
stringhe = ["{:12.5}".format(n) for n in numeri]
print("Colonna 1".center(12))
for s in stringhe:
print(s)
format()
è potente ma complesso, leggete la documentazione e gli esempi per i dettagli su come usarlo.
"stringa".ljust(20, "-") # esiste anche rjust
"stringa".center(20, "-")
" stringa ".strip() # lstrip/rstrip
"stringa".replace("i", "o")
"collo" in "colloquio"
"ciao ci sentiamo".count("ci") # numero di occorrenze di "ci"
"stringalunga".find("inga") # indice di "inga"
"Prova prova".endswith("ova") # esiste anche startswith()
"maggior rispetto e leggibilità".upper() # esiste anche lower()
"ciao ci sentiamo".capitalize()
"a,bi,ci,di".split(",")
" - ".join(["uno", "due", "tre"])
Ci sono molti altri metodi. Consultate la documentazione!
Python include una enorme libreria standard.
Prima di scrivere codice controllate se esiste modulo che risolve il vostro problema!
docs.python.org/3/library/index.html
Vediamo un po' di moduli che potrebbero esservi utili.
Contiene funzioni per calcolare potenze, radici, logaritmi, funzioni trigononometriche.
import math
math.sqrt(2)
math.sin(math.pi)
math.log(math.e)
math.exp(3) # calcola e^3
Contiene funzioni per generare numeri e scelte casuali
import random
random.choice(["uno", "a", "caso"])
random.random() # numero casuale N. 0 <= N < 1.0
random.randint(10, 20) # numero casuale N. 10 <= N <= 20
random.gauss(5, 2) # numero casuale da distribuzione normale
Non usatelo per crittografia (usate os.urandom
)
Meglio ancora, non inventate i vostri algoritmi crittografici.
Funzioni per ottenere, misurare e manipolare date e orari
import time
time.time() # secondi dal 01/01/1970 00:00:00 UTC
time.sleep(2.5) # sospende il processo per 2.5 secondi
t = time.gmtime() # oggetto rappresentante l'ora corrente
time.strftime("%H:%M %d/%m/%y", t)
time.strptime("17:04 08/05/19", "%H:%M %d/%m/%y")
Funzioni per stampare log
import logging
logger = logging.getLogger()
# Livelli predefiniti: DEBUG, INFO, WARNING, ERROR, CRITICAL
logger.setLevel(logging.WARNING)
logger.debug("Debug message") # Non viene mostrato (DEBUG < INFO)
logger.warning("Warning message") # Viene mostrato (WARNING > INFO)
Iteratori, combinazioni, permutazioni, ...
import itertools
itertools.combinations([1,2,3], 2) # Combinazioni senza ripetizioni. Ritorna un generatore!
list(itertools.combinations([1,2,3], 2)) # conversione a lista
list(itertools.product([1,2], [3,4], [5,6])) # prodotto cartesiano
Funzioni per cercare/modificare testo usando regex.
import re
pattern = "[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+"
mail_re = re.compile(pattern)
testo = "Un lungo testo contenente indirizzi@email.com ma anche altro, prova@test.it"
# Ricerca
mail_re.findall(testo)
# Sostituzione
mail_re.sub("<nospam>", testo)
Le regex sono stringhe che specificano un pattern.
Qui trovate una guida docs.python.org/3/howto/regex.html#regex-howto
Python ha un ecosistema di librerie contribuite dagli utenti.
Per installarle si utilizza pip
.
È buona prassi mantenere un ambiente isolato per ogni progetto, usando virtualenv
.
$ # creazione
$ python -m venv miovirtualenv
$ # attivazione
$ source miovirtualenv/bin/activate
(miovirtualenv) $ # installazione nel virtualenv attivo
(miovirtualenv) $ pip install getch
(miovirtualenv) $ # esecuzione nel virtualenv attivo
(miovirtualenv) $ python mioscript.py
(miovirtualenv) $ pip uninstall getch
(miovirtualenv) $ deactivate
# rimozione
$ rm -rf miovirtualenv
Per dividere il codice in più file si creano dei moduli.
Un modulo è una di queste due cose:
modulo.py
, oppuremodulo
__init__.py
È possibile importare codice in due modi:
import modulo
from modulo import funzione_1, funzione_2
Al momento dell'import il codice di modulo.py
o di __init__.py
viene eseguito, e le funzioni e variabili globali vengono rese importabili
Rilasciato sotto licenza Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International