giovedì 22 novembre 2012

Mission Python: Moduli - 1

 Salve!
E' arrivato il momento di leggere (e studiare) un altro post del caro Juhan. Detto tra noi, ritengo che sia un articolo di rara bellezza...

Io ho spesso da calcolare l'area e il perimetro di figure, in particolare di cerchi e quadrati; allora (calcfig0.py):


#!/usr/bin/python
# -*- coding: utf-8 -*-

def cerchio(raggio):
 PI = 3.14159265
 area = round(PI * raggio * raggio, 2)
 perimetro = round(2 * PI * raggio, 2)
 return area, perimetro

def quadrato(lato):
 area = lato * lato
 perimetro = 4 * lato
 return area, perimetro
 
#main
c5 = cerchio(5)
ac5 = c5[0]
pc5 = c5[1]
print "cerchio con raggio 5, area =", ac5, "perimetro =", pc5

ac8, pc8 = cerchio(8)
print "cerchio con raggio 8, area =", ac8, "perimetro =", pc8

aq7, pq7 = quadrato(12)
print "quadrato con lato 12, area =", aq7, "perimetro =", pq7

OK! Ci sono un po' di cose nuove da vedere:
  • le due funzioni ritornano una tupla (non ne abbiamo ancora parlato, è quasi come una lista) di due elementi, area e perimetro;
  • i valori ritornati possono essere memorizzati in una lista (come nel caso di c5) o come variabili float (come ac8 e pc8);
  • visto che PI è irrazionale e noi di tutte quelle cifre decimali non ce ne facciamo niente, usiamo round(). Round? Vedi qui.
Ma non è di questo che volevo trattare oggi. Oggi si parla di moduli.
Probabilmente due funzioni come cerchio() e quadrato() si useranno spesso. La soluzione di salvarle su un file e copiarlo ogni volta che serve per un nuovo script è poco elegante. E se poi faccio una modifica devo correggere tutti gli script, con il rischio di dimenticarne qualcuno, e poi è un lavoro ripetitivo.

OK, ci sono i moduli per quello!
Su un file (figure.py) mettiamo solo le due funzioni, così
PI = 3.14159265

def cerchio(raggio):
 area = round(PI * raggio * raggio, 2)
 perimetro = round(2 * PI * raggio, 2)
 return area, perimetro

def quadrato(lato):
 area = lato * lato
 perimetro = 4 * lato
 return area, perimetro

questo sarà il modulo che utilizzeremo nel nostro script (calcfig1.py):
#!/usr/bin/python
# -*- coding: utf-8 -*-

import figure
 
#main
c5 = figure.cerchio(5)
ac5 = c5[0]
pc5 = c5[1]
print "cerchio con raggio 5, area =", ac5, "perimetro =", pc5

ac8, pc8 = figure.cerchio(8)
print "cerchio con raggio 8, area =", ac8, "perimetro =", pc8

aq7, pq7 = figure.quadrato(12)
print "quadrato con lato 12, area =", aq7, "perimetro =", pq7

L'output è identico a quello precedente, provate se non ci credete.

Dovremo semplicemente dire a Python che importiamo il modulo figure (visto: stesso nome del file, senza estensione) con l'istruzione import.
Le funzioni saranno invocate (chiamate) con ., es. figure.cerchio(5).
Già che ci siamo, PI lo portiamo fuori dalla funzione così potremo chiamarlo per conto suo:

In realtà vedremo in seguito quando parleremo delle classi che i moduli di solito contengono parecchio di più.

Se vogliamo sapere cosa contiene il nostro modulo possiamo chiederlo a Python, senza aprire il file, così
come vedete c'è la costante PI e le due funzioni cerchio() e quadrato().

In __file__ c'è il nome del file utilizzato con import
Il file con estensione .pyc viene creato automaticamente con la prima importazione e ricreato dopo ogni modifica.

Esiste un altro modo di importare un modulo (calcfig2.py):
#!/usr/bin/python
# -*- coding: utf-8 -*-

from figure import *
 
#main
c5 = cerchio(5)
ac5 = c5[0]
pc5 = c5[1]
print "cerchio con raggio 5, area =", ac5, "perimetro =", pc5

ac8, pc8 = cerchio(8)
print "cerchio con raggio 8, area =", ac8, "perimetro =", pc8

aq7, pq7 = quadrato(12)
print "quadrato con lato 12, area =", aq7, "perimetro =", pq7

L'output è sempre quello...

In questo modo non avremo più bisogno di usare il nome del modulo per le funzioni, ma c'è il rischio di collisioni, quando una variabile globale (visibile come PI) o una funzione hanno lo stesso nome di un oggetto dello script.

Se il nome del modulo è lungo o non ci piace possiamo poi importarlo in questo modo:
Possiamo anche importare selettivamente quello che ci serve

Naturalmente lo script può essere eseguito da qualsiasi directory
(visto che non conviene usare nomi con spazi?). L'importante è che il file del modulo si trovi nella stessa directory dello script, anche se i pythonisti esperti direbbero che non è vero (se volete cercate PYTHONPATH nell'help online).

Il consiglio, secondo noi, sarebbe: 1) cambiare nome allo script togliendo l'estensione .py; 2) renderlo eseguibile con chmod; 3) spostarlo (con il modulo) in ~/bin in modo che sia automaticamente visibile da qualsiasi dir, senza bisogno di usare il nome del percorso.
Ma tutto questo lo sapete già, vero? Altrimenti ci possiamo sempre tornare; ditecelo eh...

Juhan

Per chi ancora non lo sapesse (ma tanto lo ripeto in ogni post) l'indice di Mission Python lo può trovare qui.

2 commenti:

  1. Scusate, il comando chmod esiste anche sotto Windows? In quale modulo si trova? Se lo digito al prompt, non lo riconosce.

    RispondiElimina
  2. Purtroppo non uso windows...giro la domanda al caro Juhan...

    RispondiElimina