«[Figlio dell'uomo] Porgi l'orecchio e ascolta le parole di KGB
e applica la tua mente alla SUA istruzione
» Pv. 22,17

Qui si straparla di vari argomenti:
1. Il genere dei pezzi è segnalato da varie immagini, vedi Legenda
2. Per contattarmi e istruzioni per i nuovi lettori (occasionali e non) qui
3. L'ultimo corto è questo
4. Molti articoli di questo blog fanno riferimento a definizioni e concetti che ho enunciato nella mia Epitome gratuitamente scaricabile QUI. Tali riferimenti sono identificati da una “E” fra parentesi quadre e uno o più capitoli. Per esempio: ([E] 5.1 e 5.4)

domenica 2 dicembre 2018

Pitoni e bachi

Come deciso nella conclusione di Reti smagliate ho guardato con più cognizione di causa cosa avevo a disposizione fra i libri comprati in blocco. Ovviamente nessuno era su Keras come speravo; molti usano il linguaggio R un altro paio il Python e (forse) ce n’è uno anche per Java…
Quindi, seguendo il piano stabilito, mi cercherò un minicorso di Keras in linea prima di proseguire con il libro di esercizi pratici in maniera da capire poi meglio quello che leggerò.
Prima però ho dato la precedenze a un minicorso di Python altrimenti mi sarei trascinato dietro una difficoltà di comprensione del codice molto fastidiosa.

Fra ieri e oggi mi sono quindi studiato un minicorso di Python per chiarirmi degli aspetti del linguaggio che non mi erano evidenti leggendo direttamente il codice.
In verità non mi sono impegnato molto per trovare un buon corso ma ho scelto il primo che mi sembrava decente (tipo il terzo o quarto propostomi da Google), ovvero il seguente: ThePythonGuru.com.
Ho seguito sia la sezione “Beginning Python” che la “Advanced Python”: ciascuna sezione è divisa su più pagine che illustrano specifici argomenti del linguaggio. Sono decisamente superficiali ma danno quell’infarinatura che mi serviva.

Nel pezzo di oggi voglio divertirmi a riportare tutte le stranezze del Python che NON mi sono piaciute (molte altre, e ben di più, le ho invece apprezzate!).

1. le “tuple” vengono definite tramite parentesi tonde.
Questo mi ha confuso molto nella lettura del codice perché le parentesi tonde sono usate anche nelle espressioni e nell’invocazione di funzioni. Contemporaneamente per sequenze e dizionari si usano invece parentesi specifiche (quadre e graffe) e quindi mi sarei aspettato delle parentesi speciali anche per le tuple. Lo so che non ci sono altre parentesi a portata di tastiera ma si sarebbe potuto usare una combinazione di due caratteri, tipo <| e |> per identificarle chiaramente.
Tipicamente quando leggevo il codice non facevo caso a queste parentesi esterne e poi non capivo a cosa si riferissero (ad esempio) le parentesi quadre successive tipo [-10:] (*1). Tutto invece mi sarebbe stato più chiaro, anche a colpo d'occhio, usando delle specifiche parentesi.

2. Separazione fisica delle librerie.
Come spiegato in Python virtualenv Guide per evitare confusione fra versioni diverse della stessa libreria si crea una vero e proprio ambiente di lavoro distinto per ogni progetto.
Non so, suppongo che questa necessità possa derivare dal fatto che di Python ne esistono due versioni fra loro incompatibili: la 2.7 e quelle dalla 3 in poi…
Ma non capisco perché non adottare una separazione logica invece che fisica: cioè nella dichiarazione dei moduli (librerie) usati obbligare a indicare anche la versione voluta.
Invece nella situazione attuale se due progetti usano la stessa libreria questa viene installata due volte negli ambienti dei due progetti!

3. Definizione di variabili private basata sul nome!
Le variabili private di un oggetto sono identificate tramite il doppio underscore iniziale, ovvero __.
Secondo me era più logico e chiaro usare un’apposita parola chiave tipo “private”.
Probabilmente si è scelta la soluzione col __ perché in Python le variabili si possono usare direttamente senza bisogno di dichiararle in anticipo. Ma per le variabili private di un oggetto avrei fatto un’eccezione invece di basarmi sul loro nome per identificarle come tali…

4. Dichiarazione dei metodi di un oggetto con parola chiave “self”.
Nella definizione dei metodi di un oggetto il primo parametro è “self”. Questo parametro non è poi passato quando tali metodi sono invocati.
Suppongo che se un metodo non ha la parola “self” come primo parametro allora sia una specie di metodo statico Java, ovvero non legato alla particolare istanza dell’oggetto ma comune a tutti quelli dello stesso tipo.
Ma se anche questo fosse il caso allora mi sarebbe sembrato più logico identificare questi particolari metodi (usati molto più raramente) con una specifica parola chiave (tipo “static”) e togliere la necessità di inserire il parametro “self” in tutti gli altri metodi...

5. Il comando “yield” per restituire un oggetto di tipo Iteratore.
Suppongo che la necessità di usare una specifica parola chiave sia dovuta al fatto che Python non definisce in anticipo il tipo di una variabile. Non si può quindi scrivere “a” è di tipo Iteratore a tempo di compilazione ma lo si potrebbe scoprire solo a tempo di esecuzione (ad esempio usando la funzione “type”). Quindi se si vogliono effettuare controlli al tempo di compilazione si usa il trucco di usare una specifica parola chiave per identificare il tipo di un oggetto!
Ecco “trucco” mi pare una parola importante nella definizione del linguaggio Python: mi sembra che alcune scelte, a mio parere discutibili, siano state fatte come sorta di trucchi per rendere più semplice la scrittura dell’interprete…

Ah! e poi credo di aver perfino trovato un baco nell’interprete (Python 3.6.7 su linux)!
Ho scritto il seguente programmino in un archivio chiamato “baco.py”:
import pickle

f=open("pick.dat",'wb')
pickle.dump(11,f)
pickle.dump("Mamma mia dammi 100$",f)
pickle.dump([1,2,4,5],f)
f.close

g=open("pick.dat", "rb")
letto=pickle.load(g)
print(letto)
g.close()

Il programmino crea un archivio chiamato “pick.dat” e vi inserisce tre oggetti in formato binario: il numero 11, la stringa "Mamma mia dammi 100$" e la sequenza [1,2,4,5]. Poi l’archivio viene chiuso e immediatamente riaperto. La seconda sezione del codice dovrebbe leggere (e successivamente stampare) il primo oggetto in formato binario dal medesimo archivio, ovvero il numero 11.
Invece si ottiene il messaggio di errore:
Traceback (most recent call last):
File "baco.py", line 10, in
letto=pickle.load(g)
EOFError: Ran out of input

In pratica il tentativo di lettura finisce perché l’archivio è già terminato. Fortunatamente per queste cose ho naso: mi sono immaginato che, per qualche motivo (il baco), l’archivio non venisse aperto alla posizione iniziale ma dal fondo. Allora ho provato a commentare la prima sezione e, in questa maniera, funziona!
Cioè:
import pickle

#f=open("pick.dat",'wb')
#pickle.dump(11,f)
#pickle.dump("Mamma mia dammi 100$",f)
#pickle.dump([1,2,4,5],f)
#f.close

g=open("pick.dat", "rb")
letto=pickle.load(g)
print(letto)
g.close()

Stampa correttamente il numero 11!
Non so, magari il baco è legato alla gestione degli archivi del sistema operativo linux, però… non dovrebbe accadere!

Conclusione: per onestà col Python dovrei anche mostrare le parti del linguaggio che invece mi sono piaciute ma in realtà sono troppe! E comunque mi pare più interessante evidenziare, motivandoli, i dettagli che non mi sono piaciuti…
E adesso mi cerco un corso di Keras!

Nota (*1): queste parentesi quadre non indicano una sequenza ma servono per “sezionare” la tupla. In particolare [-10:] ne seleziona gli ultimi dieci elementi partendo da destra.

Nessun commento:

Posta un commento