# %% RECAP # genero una lista di 20 parole casuali con lettere ripetute from random import randint, choices alfabeto = 'abcdefghijklmnopqrstuvwxyz' L = [ ''.join(choices(alfabeto, k=randint(2,10))) for _ in range(20) ] # %%% - sort/sorted con key=funzione def ordinamento(parola): return -len(parola), parola S = sorted(L, key=ordinamento) # perchè: esempio della Schwartzian transform (Perl) # genero una lista di coppie contiene i valori calcolati dal criterio di ordinamento E la loro posizione T = [ (ordinamento(X),i) for i,X in enumerate(L) ] # se la ordino ottengo la stessa sequenza prodotta da sorted E INOLTRE mantengo lìordinamento stabile O = sorted(T) # alla fine estraggo da L i valori originali nell'ordine che ho ottenuto risultato = [ L[posizione] for coppia,posizione in O ] # e si vede che ottengo la stessa sequenza di valori che avevo ottenuto con sorted print(S==risultato) # %%% - funzioni definite dentro funzioni # posso definire una funzione dentro un'altra funzione ed usarla SOLO nella funzione contenitore def esercizio2(A,B): def somma(x,y): return x+y return somma(A,B) # la funzione che definisco può leggere i valori delle variabili della funzione contenitore # in questo caso ne approfitto per calcolare la somma A+B senza dover passare i valori a somma # perchè somma se li può leggere direttamente def esercizio3(A,B): def somma(): return A+B return somma() # qui invece definisco una funzione anonima identica alla funzione precedente (tra parentesi) e poi la applico def esercizio4(A,B): return (lambda : A+B)() print(esercizio2(3, 5)) print(esercizio3(3, 5)) print(esercizio4(3, 5)) # - possono usare gli argomenti e le vars definiti dalla funzione che le contiene # - non sono disponibili fuori dalla funzione # %%% - funzioni anonime (lambda) # - solo per trasformazioni elementari che si possono esprimere con una sola espressione # %%% funzioni su liste # esistono delle funzioni che applicano funzioni su liste di elementi # map applica la funzione che le viene passata come primo argomento # alle liste che le vengono passate come secondo, terzo e così via numeri = [1, 3, 5, 22, 89, 42, 45] cubi = [ x**3 for x in numeri] cubi2 = list(map( lambda x: x**3 , numeri )) # definisco un predicato, ovvero una funzione che torna True/False def is_pari(Y): return Y%2 == 0 # per selezionare il sottoinsieme di elementi che soddisfano un predicato # lo posso fare con una list comprehension cubi_pari = [ x**3 for x in numeri if x % 2 == 0 ] #oppure con filter, passando il predicato come primo argomento cubi_pari2 = list(filter( is_pari ,cubi2)) # applicando il predicato is_pari a tutti gli elementi della lista ottengo una lista di True/False print(list(map(is_pari, cubi))) # con la funzione 'any' ottengo True se almeno uno è True (in pratica calcolo l'or logico) esempio_any = any(map(is_pari, cubi)) # con la funzione 'all' ottengo True se tutti sono True (in pratica calcolo l'and logico) esempio_all = all(map(is_pari, cubi)) # %% FILES # %%% F = open(path, mode=..., encoding=...) # open: costruzione di un oggetto che fa da interfaccia al file su HD # mode: 'r', 'w', 'a' con il modificatore 't' o 'b' # encoding: # se voglio aprire un file di testo e scriverci F = open("pippo.txt", encoding='utf8', mode='w') # posso usare 'write' per scrivere un testo (ricordando di metterci l'accapo in fondo alla riga) F.write("pippo è andato al mare\n") # oppure usare print con il parametro 'file' print("kjglahgkjhkj kajhhk gj", file=F) # oppure riusare write F.write("pippo è andato al mare\n") # ALLA FINE DEVO CHIUDERE IL FILE F.close() # %%% F.close() # rilascio delle strutture dati e salvataggio su HD # %%% with open() as F: # MOLTO MEGLIO: uso la parola chiave 'with' per aprire un "contesto" in cui apro il file # e che mi assicura che il file verrà chiuso correttamente SEMPRE (anche in caso di eccezioni) with open('topolino.txt', mode='w', encoding='utf8') as F: F.write("pippo è andato al mare\n") print("kjglahgkjhkj kajhhk gj", file=F) F.write("pippo è andato al mare\n") assert False # anche se inserisco un errore il file viene salvato # BAD STYLE: non conviene usare direttamente open e close # - errori ed eccezioni # semplici dimenticanze # %%% F.seek(posizione) # per posizionarsi in un certo punto del file (0=inizio) # se voglio leggere il file e stamparlo 2 volte with open('topolino.txt', encoding='utf8') as F: testo = F.read() print(testo) testo = F.read() # la seconda volta sono in fondo al file e non leggo niente print('===================') print(testo) # %%% F.read readline, readlines # read: lettura di tutto il file (ok con file binari) # readline: lettura da un file di testo di una linea per volta # readlines: tutte assieme # readline legge una riga (con in fondo l'accapo) with open('topolino.txt', encoding='utf8') as F: riga = F.readline() print("$", riga.strip(), "$") # readlines legge tutte le righe e torna una lista di stringhe (con gli accapi) with open('topolino.txt', encoding='utf8') as F: righe = F.readlines() for riga in righe: print(riga) # %%% for line in F: # scansione di un file riga per riga # ma se voglio usare meno memoria posso usare direttamente F come un generatore di righe with open('topolino.txt', encoding='utf8') as F: for riga in F: # per ciascuna richiesta viene tornata la prossima riga print(riga) # %%% provo ad usare seek per tornare all'inizio e ripetere la stampa with open('topolino.txt', encoding='utf8') as F: for riga in F: # scandisco le righe del file print(riga) # e le stampo F.seek(0) # mi riporto all'inizio del file for riga in F: # di nuovo scandisco le righe del file print(riga) # %% LUNEDI': analisi del testo e ricerca # files e loro encoding files = { 'files/holmes.txt' : 'utf-8-sig', 'files/alice.txt' : 'utf-8-sig', 'files/frankenstein.txt' : 'utf-8-sig', 'files/alice_it.txt' : 'latin', 'files/prince.txt' : 'utf-8-sig' } # %%% - estrazione delle parole (rimpiazzando i nonalpha con spazi) # %%% - costruzione di indici per evitare di dover ricontare le parole # %%% - eliminazione delle parole più comuni (con frequenze molto/troppo alte, con stopwords) # %%% - ricerca di file che parlano di più di certe parole # %%% - importanza delle parole nei file = tf_i * idf # - tf_i = # presenze / # parole del file # frequenza nel file iesimo # - idf = log( # di file / # di file che contengono la parola ) # inverso della frequenza nei documenti