Python.corso.scai
Python.corso.scai
science
Contenuti
• Cosa è Python
• Linguaggi compilati vs interpretati
• Python per il calcolo scinetifico tecnico
• Esempi
Python sta per Pitone?
• Il nome deriva da “Monty Python's Flying Circus” (famoso
gruppo di comici inglese di cui il padre di Python, GuidoVan
Rossum, è grande fan)
• Ciononostante, numerosi libri e pubblicazioni/progetti di e su
Python usano il pitone come animale simbolo
Cosa è python
• Python è stato creato agli inizi degli anni 90 da Guido van Rossum al
Centro di Matematica di Stichting (CWI, si veda http://www.cwi.nl/)
nei Paesi Bassi, come successore di un linguaggio chiamato ABC.
Guido rimane l’autore principale di Python, anche se molti altri vi
hanno contribuito.
• Nel 1995, Guido continua il suo lavoro su Python presso il Centro
Nazionale di Ricerca (CNRI, si veda http://www.cnri.reston.va.us/) in
Reston, Virginia, dove ha rilasciato parecchie versioni del software.
Interpretato Compilato
Python C/C++
Matlab ® Fortran
Perl Java
Due famiglie di linguaggi
LINGUAGGI LINGUAGGI COMPILATI
INTERPRETATI
codice
interpretato codice macchina
Interprete VS Compilatore
COMPILATORE
• Il processo di compilazione è costituito da diverse fasi
costi
benefici
Costi e Benefici
• Velocità di esecuzione: i linguaggi compilati hanno in generale prestazioni
migliori dei linguaggi interpretati (compilazione ottimizzata)
• Velocità di sviluppo: i linguaggi interpretati sono di alto livello, la messa a
punto del codice è più semplice, sia per semplicità di programmazione, sia
perché gli interpreti permettono di correggere gli errori non appena
vengono scoperti, senza necessità di ricompilazione
• Portabilità del codice: su piattaforme hardware/software diverse da quelle
su cui il codice è stato sviluppato.
– Per un codice compilato:
– Portabilità dell’eseguibile su piattaforme con hardware,
software simile e quello su cui il codice è stato compilato
– Portabilità tramite ricompilazione: esistenza di compilatori e
librerie.
– Per un codice interpretato:
– Esistenza di un interprete sulla nuova piattaforma.
Due famiglie di linguaggi
Definizioni alternative
Possibile definire I linguaggi distinguendoli anche per utilizzo o
per caratteristiche macroscopiche. In questo caso si potrebbe
parlare di linguaggi:
PYTHON
print '3'+4
Traceback (most recent call last):
File "<pyshell#196>", line 1, in <module>
print '3'+4
TypeError: cannot concatenate 'str' and 'int' objects
Duck typing/Nominal Typing
Nominal Typing
• Buona parte dei linguaggi compilati eseguono un typing nominale.
Due oggetti si riferiscono allo steso tipo se le loro dichiarazioni sono identiche. Il tipo è noto a tempo di
compilazione.
Duck Typing
• “if it walks like a duck, and quacks like a duck, then it is a duck”
• Nel duck – typing il controllo sul tipo è fatto solo a tempo di esecuzione
>>> l = [1, 2, 3]
>>> d = { 0: 0, 'a': 2, 'b': 4 }
>>> i = 4
>>> print l[0] + 3, d[0]+3
(4,3)
>>> print i[0] + 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is unsubscriptable
The Zen of Python
• Python è un linguaggio di programmazione con molti aspetti
positivi:
– Grande semplicità d'uso
– Grande semplicità di apprendimento (assomiglia alla
pseudocodifica)
– Grande leggibilità (c'è un solo modo per fare qualsiasi cosa)
– Grande portabilità.
Python sì
Python per applicazioni scientifiche
• Python Success Stories
oppure:
from os import *
from os import
from os import path as PP
import os
import os as O
Esempio-2.0
import os
#importo lo spazio dei nomi del modulo os
>>> os.curdir
’.’
>>> os.getenv('HOME')
'C:\\Documents and Settings\\ponzini.CILEA-DOM.000'
>>> os.listdir('.')
['aboutDialog.py', 'aboutDialog.pyc', 'AutoComplete.py', 'AutoComplete.pyc',
'AutoCompleteWindow.py', 'AutoCompleteWindow.pyc', 'AutoExpand.py',
'AutoExpand.pyc', 'Bindings.py', 'Bindings.pyc', 'CallTips.py', 'CallTips.pyc',
'CallTipWindow.py', 'CallTipWindow.pyc', 'Clas….]
>>> os.defpath
'.;C:\\bin'
Esempio-2.1
import os as O
#importo lo spazio dei nomi del modulo os come O
>>> O.curdir
’.’
>>> O.getenv('HOME')
'C:\\Documents and Settings\\ponzini.CILEA-DOM.000'
>>> O.listdir('.')
['aboutDialog.py', 'aboutDialog.pyc', 'AutoComplete.py', 'AutoComplete.pyc',
'AutoCompleteWindow.py', 'AutoCompleteWindow.pyc', 'AutoExpand.py',
'AutoExpand.pyc', 'Bindings.py', 'Bindings.pyc', 'CallTips.py', 'CallTips.pyc',
'CallTipWindow.py', 'CallTipWindow.pyc', 'Clas….]
>>> O.defpath
'.;C:\\bin'
Esempio-2.3
from os import *
#importo tutto dallo spazio dei nomi del modulo os
>>> curdir
’.’
>>> getenv('HOME')
'C:\\Documents and Settings\\ponzini.CILEA-DOM.000'
>>> listdir('.')
['aboutDialog.py', 'aboutDialog.pyc', 'AutoComplete.py', 'AutoComplete.pyc',
'AutoCompleteWindow.py', 'AutoCompleteWindow.pyc', 'AutoExpand.py',
'AutoExpand.pyc', 'Bindings.py', 'Bindings.pyc', 'CallTips.py', 'CallTips.pyc',
'CallTipWindow.py', 'CallTipWindow.pyc', 'Clas….]
>>> defpath
'.;C:\\bin'
Esempio-2.4
FUNZIONI
mondo
DATI
esterno
QUERY
Sintassi di un oggetto
Alcune nozioni base sulla sintassi degli oggetti e sulle modalità di accesso ai membri,
prima di procedere formalmente alla definizione delle classi:
Classes:
Pickler
Unpickler
Commenti
Functions:
dump(object, file)
dumps(object) -> string
load(file) -> object
loads(string) -> object
Misc variables:
__version__
format_version
compatible_formats
if __name__== ‘__main__’:
print ‘Il chiamante sono proprio io’
else:
print ‘sono stato importato da un altro modulo’
help()
Analogamente a quanto mostrato per la funzione di sistema dir()
che ha validità generale per ogni modulo/oggetto, è anche
disponibile una funzione di sistema per conoscere la
documentazione su una generica funzione:
import pickle
>>> help(pickle.dump)
Help on function dump in module pickle:
>>> help(pickle.load)
Help on function load in module pickle:
Type()
• Determinare il tipo di un’oggetto in Python è estremamente
facile: basta usare il comando type.
>>>a=5
>>>type(a)
<type’int’>
>>> l = [1, "alfa", 0.9, (1, 2, 3)]
>>> print [type(i) for i in l]
[<type 'int'>, <type 'str'>, <type
'float'>, <type 'tuple'>]
>>>
Moduli creati dall’utente
• Tutto quanto mostrato sulle funzioni di sistema per l’introspezione dei
moduli, degli oggetti e delle funzioni vale anche per il codice prodotto
dall’utente.
#file mymodule.py
“””this is the documentation section of my module
usually here I explain who is author; what the module does; the functions provided;
lincesing
“””
_eps=0.001
def myfunc(var1,var2):
“”” this function compare two values and print out the largest one:
-IN: var1; var2
-OUT: none
-usage: myfunc(var1,var2)
“””
if var1>var2: print ‘largest value between input:’, var1
elif var1==var2: print ‘the two value are equal’
else: print ‘largest value between input:’, var2
Moduli creati dall’utente
from mymodule import *
#import mymodule
## import mymodule as M
>> dir()
>> ['__builtins__', '__doc__', '__name__', 'myfunc‘,’_eps’]
#dir(mymodule)
help(myfunc)
Help on function myfunc in module __main__:
myfunc(var1, var2)
this function compare two values and print out the largest one:
-IN: var1; var2
-OUT: none
-usage: myfunc(var1,var2)
#help(mymodule.myfunc)
##help(M.myfunc)
Test
• Download e Installazioni
• Hands-on
Installazione Python
• Python può essere utilizzato su diverse piattaforme
Linux,Macintosh, Windows.
• La distribuzione principale di python è scaricabile
http://www.python.org/
$ export PYTHONPATH=$HOME
>>> import sys
>>> sys.path
['', '/home/interni/alinve',
'/usr/lib64/python24.zip', '/usr/lib64/python2.4',
'/usr/lib64/python2.4/plat-linux2',
'/usr/lib64/python2.4/lib-tk',
'/usr/lib64/python2.4/lib-dynload',
'/usr/lib64/python2.4/site-packages',
'/usr/lib64/python2.4/site-packages/Numeric',
'/usr/lib64/python2.4/site-packages/PIL',
'/usr/lib64/python2.4/site-packages/gtk-2.0',
'/usr/lib/python2.4/site-packages']
Installazione Python
>>>help('modules')
Please wait a moment while I gather a list
of all available modules...
Installazione base: IDLE
IDLE: è l’interfaccia built-in di Python sviluppata con la libreria
base GUI (tkinter). IDLE ha seguenti caratteristiche:
• 100% puro Python
• cross-platform: windows/linux
• text editor multi-window con multipli undo
• colorazione del testo basato sulla sintassi Python ed
indentazione automatica del testo.
• completamento delle funzioni
• interprete interattivo
• debugger
• necessita della libreria Tk
Installazione with bacteries included
Esistono installazioni specifiche per il calcolo scientifico e le
applicazioni ingegneristiche che contengono già numerosi
moduli di utilità:
• Enthought (largamente la più diffusa e con un livello di
mantenimento e di investimenti significativo)
• L’installazione la si può scaricare dal link:
http://www.enthought.com/
Cosa contiene:
http://www.enthought.com/products/epdlibraries.php
Installazione with bacteries included
Caratteristiche:
• Visualizzazione della lista dei metodi e delle proprietà di ogni variabile
premendo il tasto TAB.
• Visualizzazione della documentazione di ogni oggetto e funzione in
maniera semplice e immediata: nome_funzione?<enter>
• Definizione di comandi personalizzati e di alias (es. %alias l ls -la).
• Possibilità di eseguire comandi di sistema (es. !ls) e di recuperare il loro
output sotto forma di stringa o lista (ipython -p pysh, $$v=ls).
• Mantiene uno storico dei comandi eseguiti (%hist, _ih).
• Integrabile nei programmi come utile strumento per il debugging.
• molto altro…
Demo / Hands on
Connessione ai pc linux
• apertura Ipython
• esecuzione comandi
• lancio di script (#!/bin/python/ e PYTHONPATH)
• comando sys.argv[*]
• comando help()
• introspezione (dir module)
• import pylab
• simple-plot
Note: indentazione/blocchi
• python si basa sulla indentazione del codice
• blocchi logicamente connessi hanno lo stesso livello di indentazione
x = 2.3
y = 1.2
def test(x,y):
if x==y: print 'the two number are equal'
elif x > y: print ' the first number is the greater'
else: print ' the former number is the greater'
test(x,y)
for I in range(2,5,1):
for J in range(5,1,-1):
print 'now testing : ', I,J
test(I,J)
Modalità di lancio
Uno script python può essere lanciato in vari modi:
1) [ponzini@prompt] python script.py
(implica che nel PATH o nel PYTHONPATH sia indicata la locazione di
installazione di python)
• Uno script python può avere o meno parametri di input necessari alla
corretta esecuzione dello script:
• Per prevedere questa modalità di lancio si può fare uso degli appositi
parametri argv[*] contenuti nel modulo sys:
– argv[0]: nome dello script che stiamo eseguendo
– argv[i]: qualsiasi parametro_i
Esempio
# script che prende 2 parametri di input
import sys
usage="""necessita di due parametri di input (param1, param2)
correct usage: python script.py param1 param2"""
if __name__ == '__main__':
if len(sys.argv) < 2:
print 'lo script: ',sys.argv[0],usage
sys.exit(0) # termina dopo aver stampato la stringa di usage
param1 = sys.argv[1]
param2 = sys.argv[2]
print 'uso I due parametri passati al momento dell’invocazione dello
script:\ ',param1, param2
raw_input()
Nel caso si volesse invece avere una interazione con l’utente dello script è possibile
fare uso di una funzione predisposta per accettare parametri a run-time dallo
stdin.
Esempio:
# script che prende 2 parametri di input
import sys
if __name__ == '__main__':
while(True):
print 'PLEASE INSERT AN INTEGER NUMBER IN THE RANGE 0-10'
param1 = raw_input()
if int(param1) in range(11): # notare che raw_input restituisce una stringa
while(True):
print 'PLEASE INSERT A CHAR PARAMETER IN [A,B,C]'
param2 = raw_input()
if param2 in ['A','B','C']:
print 'uso I due parametri passati dall utente: ',param1,
param2
sys.exit()
else: print 'TRY AGAIN PLEASE'
else: print 'TRY AGAIN PLEASE'
input()
Come raw_input ma con un eval(): eval(raw_input(prompt))
Esempio:
if __name__ == '__main__':
while(True):
print 'PLEASE INSERT AN INTEGER NUMBER IN THE RANGE 0-10'
param1 = input() #notare che c’è eval e int() non va messo
if param1 in range(11):
while(True):
print 'PLEASE INSERT A CHAR PARAMETER IN [A,B,C]'
param2 = input() # causa eval bisogna usare il simbolo di carattere
if param2 in ['A','B','C']:
print 'uso I due parametri passati dall utente: ',param1, param2
sys.exit()
else: print 'TRY AGAIN PLEASE'
else: print 'TRY AGAIN PLEASE'
eval()
Come visto le due funzioni sembrano praticamente equivalenti ma eval() che
cosa produce:
>>> help(eval)
eval(...)
eval(source[, globals[, locals]]) -> value
import sys
def f(x):
print x
def g(x):
print -x
if __name__ == '__main__':
while(True):
print 'PLEASE INSERT AN INTEGER NUMBER IN THE RANGE 0-10'
param1 = input()
if param1 in range(11):
while(True):
print 'PLEASE INSERT THE NAME OF A FUNCTION'
param2 = input() #grazie alla presenza di eval ha senso l’istruzione che segue
if param2 in [f,g]:
print 'uso i due parametri passati dall utente: ',param1, param2
param2(param1)
sys.exit()
else: print 'TRY AGAIN PLEASE'
else: print 'TRY AGAIN PLEASE'
Tipi di Dato
Data Types
Esempio
E contenitori.
• Uno dei punti di forza di Python è nei contenitori disponibili,
che sono molto efficienti, comodi da usare, e versatili:
– tuple ()
– list []
– dict {}
– set
Tipo Numerico
Il linguaggio mette a disposizione quattro tipi numerici di dato :
• Integer
Il tipo int è valido per tutti i numeri interi che sono compresi tra
[-2147483648 e 2147483647], vedi (sys.maxint)
Un intero può essere espresso in base decimale oppure in base
esadecimale o ottale antecedendo al numero 0x e 0
rispettivamente:
Esempio
>>> a=300 #decimale
>>> b=0x12c #esadecimale
>>> c=0454 #ottale
>>> a_oct=oct(a) #ottale
>>> a_hex=hex(a) #esadecimale
Tipo Numerico
• Long Integer
Il tipo long è analogo al tipo intero con l’unica eccezione che il valore massimo e
minimo che può assumere è limitato solo dalla memoria a disposizione.
Esempio
>>> a = 1254546699L # il suffisso L indica un long type
>>> b = 484564848766
>>> b
>>> 484564848766L
>>>2**1024
17976931348623159077293051907890247336179769789423065727343008115
77326758055009631327084773224075360211201138798713933576587897688
14416622492847430639474124377767893424865485276302219601246094119
45308295208500576883815068234246288147391311054082723716335051068
4586298239947245938479716304835356329624224137216L
ESEMPIO
>>>a=2147483647
>>>type(a)
<type 'int'>
>>>a+=1
>>>type(a)
<type 'long'>
• Complex Number
Un numero complex rappresenta un tipo numerico complesso in doppia precisione. Si accede
alla parte reale e immaginaria di un numero complesso attraverso le funzioni ‘real’ e
‘imag’.
esempio
>>>r=12+5j
>>>r.imag
5.0
>>>type(r.real)
<type 'float'>
‘j’ indica la parte immaginaria
Operazioni su dati numerici
In Python le operazioni sui dati numerici sono gestite dai seguenti operatori:
• Operatori Unari: -,+,~
• Operatori Binari: -,+,*,/,%,**
• Operatori Logici (solo su int e long int): and, or, xor
• Operatori bit a bit (solo su int e long int): &, | ,^
Esistono inoltre funzioni built-in per lavorare con dati numerici, tra cui:
-abs(number)
-pow(x, y[, z])
-round(number[, ndigits])
-coerce
IntLongFloatComplex
Operazioni su Dati Numerici
Esempio:
>>> k=5
>>> s=5+j
>>> type(s+k) #conversione a numero complesso
<type 'complex'>
>>> 4 and 2 # confronto logico
2
>>> 4 & 2
0 # confronto bit a bit tra i numeri binari 100 e 10
>>> 4 | 2
6 # confronto bit a bit tra i numeri binari 100 e 10
Operazioni su Dati Numerici
>>>dir(math)
['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan',
'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp',
'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot',
'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow',
'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc']
Bool Type
E’ possibile utilizzare i valori interi per rappresentare valori booleani con la convenzione
che 0 corrisponda a FALSE e tutti i valori interi positivi corrispondano a TRUE.
E’ tuttavia buona norma di programmazione utilizzare il tipo bool per rappresentare
valori booleani. Una variabile di tipo bool può assumere valori TRUE e FALSE che
possono essere interscambiati con i valori 1 e 0
rispettivamente.
ESEMPIO
>>> a=1
>>> type(a)
<type 'int'>
>>> if(a):
print 'True'
True
>>> a=False
>>> type(a)
<type 'bool'>
Stringhe
• Una stringa letterale è una sequenza di caratteri racchiusa tra doppi o
singoli apici.
>>> a='ciao'
>>> b="Mondo"
>>> a+b
'ciaoMondo'
• Le sequenze di apici tripli “”” o ''' possono essere utilizzate per stringhe
che spaziano su più righe, o che contengono apici singoli o doppi (o tripli
dell'altro tipo):
Stringhe
Per accedere al singolo carattere si può ricorrere all’operatore [] oppure ad
una sottostringa con l’operatore [begin:end] (slicing)
Esempio
>>> a = “Hello world”
>>> a[1]
‘e’
>>> a[1:3]
‘el’
Non è possibile modificare il singolo carattere, ma è possibile assegnare alla
stringa un nuovo valore
Esempio
>>> a=‘Primo valore’
>>> a = “Change value” #Ok riassegnamento
>>> a[2] = ‘3’ #Errore
Manipolazione – Formattazione
Gli operatori + e * possono essere utilizzati per la manipolazione di stringhe.
La precedenza tra gli operatori viene mantenuta.
Esempio
>>> a = ‘Hello’
>>> a+a+a # Concatenazione
‘HelloHelloHello’
>>> a = ‘He’+’l’*2+’o World’ # Concatenazione e ripetizione
>>> a
‘Hello World’
NOTA: Oltre ai metodi built-in esiste il modulo string per la manipolazione di stringhe.
Alcune funzioni sono però già implementate come metodi nella classe str.
Confronti tra Stringhe
• Operatori logici : and, or, not
Una stringa vuota è valutata False mentre qualsiasi stringa
non vuota è valutata True.
Esempio
>>> a = ‘HelloWorld’
>>> min(a), max(a)
(‘H’,’o’)
>>>’k’ in a
False
Conversioni tra Tipi
La conversione tra tipi nativi viene eseguita attraverso specifiche funzioni.
• Conversione da tipo stringa a tipo numerico :
- int(), float(), complex(), long()
- ord()
- eval()
• Conversione da tipo numerico a stringa:
- chr()
- str()
Esempio
>>> a=97.6
>>> print ord(chr(int(a)))
97
>>> b=5+3j
>>> _+b
(102+3j)
Esempio
Esempio
from math import *
g=9.81 #m/s
v0=15 #km/h
theta=60 #degree
x=0.5 #m
y0=1 #m
print """
Dati iniziali
v0=%f km/h
theta=%d gradi
y0=%f m
x=%f m
"""%(v0,theta, y0,x)
Esempio
#conversione dati
v0=v0/3.6
thetha=degrees(thetha)
y=x*tan(theta) -1/(2*v0**2)*g*x**2/(cos(thetha)**2) + y0
print “Posizione finale = “, str(y), ‘m’
OUTPUT:
Dati
v0=15.000000
theta=60
x=0.500000
y0=1.000000
Posizione finale = 1.16002019469
Polimorfismo
Il polimorfismo garantisce caratteristiche di concisione e di
flessibilità del linguaggio.
Essendo Python un linguaggio interpretato e con typing
dinamico, il polimorfismo è intrinseco nel linguaggio.
Esempio:
def somma(a,b): OUTPUT
7
return a+b Ciao mondo
[1,2,3,3]
print somma(3,4)
print somma(‘ciao’,’ mondo’)
print somma([1,2],[3,3])
Il polimorfismo garantisce un’unica interfaccia per operare su
tipi di dati differenti.
Costrutti
Control Flow
Con control flow (o strutture di controllo) si intende l’insieme dei costrutti che
servono a gestire il flusso di esecuzione di un programma, cioè a
specificare quando e come eseguire gli statements del codice.
if condition1:
block 1
elif condition2:
block 2
…
elif conditionN:
block N
else:
block statements
Current number 4
Divided by 2
Current number 6
Divided by 2
Current number 5
Divided by 2
Divided by 3
Divided by 4
Numero primo: 5
Continue - Break
Esempio: calcolo della distanza minima tra un punto p1 e un insieme di punti nel
primo quadrante
from math import *
from pylab import*
import sys
lista=[(2,3),(4,5),(1,7),(-1,6),(-2,-4),(2,-8),(1,1)]
p1=input('Inserisci la coordinata lungo x: ')
p2=input('Inserisci la coordinata lungo y: ' )
point=(p1,p2)
c_point=()
dist_min=0
cur_dist=-1
dist=sys.float_info.max
Continue - Break
x=[]
y=[]
for k in range(len(lista)):
x.append(lista[k][0])
y.append(lista[k][1]) Jump
Escludiamo i punti fuori
if lista[k][0]<0 or lista[k][1]< 0:
dal primo quadrante
continue
cur_dist=sqrt((lista[k][0]-point[0])**2+(lista[k][1]-point[1])**2)
if cur_dist==0:
print 'Punti coincidenti'
break
if cur_dist<dist:
Break
dist=cur_dist
c_point=lista[k]
Continue - Break
plot(x,y,'o',[point[0]],[point[1]],'ro')
#OUTPUT
Inserisci la coordinata lungo x: 1
Inserisci la coordinata lungo y: 2
Distanza minima : 1.0
Punto di minimo: (1, 1)
Pass
>>>a=3
>>>b=4
>>>f(a,b)
For While & Else Clause
Ai cicli condizionali for e while può essere associato un else statement, con la
seguente sintassi:
for <variable> in <sequence>: while(condition1):
block1 block1
else: else:
block2 block2
Esempio
n2=1000
step=5
print “Number n1 is in range ( %d , %d) with step %d?”%(0,n2,step)
number=int(raw_input(“Insert number n1: “))
For While & Else Clause
for i in range(0,n2,step):
if i==n1
print ‘n1 IS in range’
break
else:
print ‘n1 IS NOT in range’
#OUTPUT:
Number n1 is in range ( 0 , 1000) with step 5
Insert n1: 77
n1 IS NOT in range
Insert n1: 55
n1 IS in range
Gestione delle Eccezioni
La gestione delle eccezioni è uno strumento che permette di gestire errori che
tipicamente si verificano durante l’esecuzione di un programma.
Questo strumento permette di aumentare la robustezza di un programma e
prevenire crash che comprometterebbero la normale esecuzione del codice.
Ci sono almeno due tipologie di errore: errori sintattici ed eccezioni, generati
quando la sintassi è corretta ma viene prodotto un errore a run-time.
Esempio:
>>> for i in range(10) print ‘Ciao’
SyntaxError: invalid syntax
>>> a = 10/0
Traceback (most recent call last):
File "<pyshell#11>", line 1, in <module>
a=10/0
ZeroDivisionError: integer division or modulo by zero
Try - Except
Il costrutto try-except permette di rilevare le eccezioni e passare il controllo di flusso
ad un blocco preposto: exception handler, con la seguente sintassi:
try :
block1
except:
block2
In questo modo viene eseguito il blocco try e se viene generato un errore l’esecuzione
prosegue nel blocco except. Qualsiasi errore viene gestito nel blocco except a
meno di specificare più blocchi except ognuno dedicato alla gestione di una
particolare tipologia di errori.
Esempio:
>>>s=input(‘Inserisci un intero: ’)
>>>a=s/10 #Ma se s=0 o s=stringa?
Try - Except
#Soluzione
query=True
while(query):
try:
s=input('Inserisci un numero: ')
a=10.0/s
print a
query=False
except NameError:
print 'Inserisci un numero'
query=True
except ZeroDivisionError:
print 'Divisione per zero!‘
query=True
Try - Except
Un except clause può gestire più tipologie di eccezioni, che vengono
specificate attraverso una tupla di valori:
except (exception1, exception2,…,exceptionN)
Il costrutto try-except può avere un else-clause opzionale.
try:
block1
except e1:
block2
…
except eN:
blockN
else:
blockN+1
L’ else-clause viene eseguito quando il costrutto try non genera eccezioni.
Try - Except
Il blocco except ammette anche la sintassi:
except ExceptionName,e :
Le informazioni aggiuntive riguardo l’oggetto che hanno causato
l’eccezione vengono salvate in e.
Esempio:
try:
s=input(“Inserisci un numero: “)
a=10.0/s
except NameError,e:
print “Errore “, e
except Exception,e:
print e
#OUTPUT:
a,b,c: 2,1,0
Le radici sono 0.0 -0.5
a,b,c: 0,2,1
Impossibile, a=0
Raise Exception
Esempio: raise-else clause
#Verificare se un elemento esiste in una matrice
found=0
for x in range(len(mat)):
for y in range(len(mat)):
k+=1
if mat[x][y]==s:
found=1
break
if found:
break
if found==1:
print 'Trovato alla '+str(k)+'-esima iterazione'
else:
print 'Non Trovato‘
Raise Exception
#Oppure
try:
for x in range(len(mat)):
for y in range(len(mat)):
k+=1
if mat[x][y]==s:
msg='Trovato alla‘ +str(k)+ '-esima iterazione'
raise Exception, msg
except Exception,msg:
print msg
else:
print 'Non trovato'
Finally Statement
Il costrutto try-except può essere integrato con lo statement opzionale finally.
Il costrutto finally serve a racchiudere un blocco di istruzioni che devono
essere eseguite in ogni caso, sia che venga o non venga generata
un’eccezione.
Se in un blocco try viene generata un’ eccezione non gestita da un exception
handler, l’eccezione viene rilanciata dopo la finally clause.
Esempio:
a=raw_input('Inserisci un numero: ')
b=raw_input('Inserisci un secondo numero: ')
try:
d=int(a)/int(b)
except ZeroDivisionError,e:
print 'Divisione per zero:', e
Finally Statement
else:
print 'Divisione: ',d
finally:
print 'Esecuzione di finally‘
#OUTPUT:
Inserisci un numero: 5
Inserisci un secondo numero: 0
Divisione per zero: integer division or modulo by zero
Esecuzione di finally
Nella pratica è utile l’utilizzo dello statement finally per controllare il rilascio
di risorse esterne p.e. chiudere un file, una connessione di rete, chiudere
una connessione con un database, ect. anche se il codice è andato in
crash.
NOTA:
Il costrutto try-except-finally è supportato a partire dalle versioni 2.5.x
Dato Strutturato
Indice
• Tipi di dato strutturato
• Liste
• Tuple
• Dictionary
• Switch Case e Dictionary
• Set/Frozen Set
• Sequenze dati e cicli
• Iteratori
• range e xrange
• shallow & deep copying
Tipo di Dato Strutturato
Oltre ai tipi di dato nativi del linguaggio come stringhe, interi, numeri in
virgola mobile o complessi, comuni anche ad altri linguaggi di
programmazione, Python fornisce delle strutture dati native del
linguaggio.
Tali strutture si suddividono in sequenze ordinate di dati o collezioni di dati.
Ma si possono anche classificare come strutture mutevoli o immutevoli.
Le built-in data structures in Python sono:
•Liste
•Tuple
•Dizionari
•Set
•Frozenset
Liste
list definisce un tipo di dato strutturato lista. Gli elementi che costituiscono
una lista possono essere istanze di oggetti nativi del linguaggio o istanze di
oggetti definiti dall’utente. Una lista può contenere contemporaneamente
elementi di diverso tipo.
Per istanziare una lista non è necessario specificare lunghezza o tipo di dato.
Gli elementi di una lista sono contenuti tra [].
Per accedere al singolo elemento della lista si ricorre all’operatore [].
Esempio:
>>>mylist=[]
>>>mylist=[‘Lista’,’di’,4,’elementi’]
>>>print mylis[2],mylist[0]
>>>4
L’ordinamento viene mantenuto. Una lista non è una collezione di dati ma è
una sequenza ordinata di dati.
Liste
• Le liste supportano l’operatore di slicing [start:stop:step]
>>> mylist =[0,1,2,3,4,5,6,7]
>>> mylist[0:6]
[0,1,2,3,4,5]
>>> mylist[1:6:2]
[1,3,5]
>>> mylist[1::2]
[1,3,5,7]
>>> mylist[::2]
[0,2,4,6]
Che è equivalente a :
>>> combs = []
>>> for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
combs.append((x, y))
• Ricerca
-index(value, [start, [stop]]) ricerca di value e ritorno della prima
occorrenza
-count(value) calcolo delle occorrenze di value
• Eliminazione
-remove(value) eliminazione della prima occorrenza di
value
-pop([index]) eliminazione elemento in posizione index
Liste
• Ordinamento
-reverse() inversione dell’ordine degli elementi
-sort(cmp=None, key=None, reverse=False) ordinamento
NOTA:
Le liste sono una struttura dati flessibile e consentono
l’immagazzinamento di dati eterogenei, a costo di più memoria.
Lavorando con dati di un solo tipo gli array (modulo numpy) sono più
performanti.
Liste
Gli operatori + e * possono essere applicati anche sulle liste.
L’operatore + effettua una concatenazione tra due liste.
L’operatore * effettua una ripetizione.
Python supporta per le liste anche l’operatore += .
L’operatore + e la funzione extend hanno le stesse funzionalità. I
tempi di esecuzione sono però differenti.
Esempio:
import time
mylist =range(100000000)
mylist2 =range(1000000)
Liste
T1=time.clock()
s= mylist + mylist2
T2=time.clock()
print “ Tempo di esecuzione di + :’’ , T2-T1 , “s”
T3=time.clock()
mylist.extend(mylist2)
T4=time.clock()
print “ Tempo di esecuzione di extend :’’, T4-T3 , “s”
OUTPUT:
Tempo di esecuzione di +: 2.81 s
Tempo di esecuzione di extend: 0.033 s
Liste
I metodi implementati nella lista la rendono particolarmente adatta ad essere
utilizzata come stack o come queue.
I metodi pop e append possono essere usati per implementare la logica LIFO tipica
degli stack.
I metodi pop con indice 0 e append possono essere usati per implementare la logica
FIFO tipica della queue.
Esempio:
# file stack_queue.py
stack=[1, 2, 3, 4]
print ‘Stack iniziale:’, stack
for i in range(5,7):
stack.append(i)
print “Append: “, stack
stack.pop()
print “Pop:” , stack
Liste
queue=[ ‘a’,’b’,’c’,’d’ ]
print “Queue iniziale:”, queue
queue.append(‘e’)
queue.append(‘f’)
print “Append:”, queue
queue.pop(0)
print “Pop:”, queue
OUTPUT:
Stack iniziale: [1, 2, 3, 4]
Append: [1, 2, 3, 4, 5, 6]
Pop: [1, 2, 3, 4, 5]
Queue iniziale: ['a', 'b', 'c', 'd']
Append: ['a', 'b', 'c', 'd', 'e', 'f']
Pop: ['b', 'c', 'd', 'e', 'f']
Tuple
Le tuple sono sequenze ordinate di dati racchiusi tra (). Le tuple sono liste molto
particolari i cui elementi sono immutabili.
L’accesso al singolo elemento avviene attraverso l’operatore [].
Lo slicing [start:end] è ammesso anche sulle tuple.
Esempio:
>>>mytuple=(1,2,3,4)
>>>el= mytuple[1]
>>>t2= mytuple[0:2]
>>>print el, t2
2 (1,2)
I dati contenuti in una tupla possono essere di tipo eterogeneo.
Le tuple sono oggetti immutabili. Non contengono pertanto metodi di:
• eliminazione
• inserimento
• ricerca
Tuple
Esempio:
>>> mytuple =(1,2,3,4,’ciao’,’mondo’,[2,3])
>>> mytuple[3]=‘jkjk’
Traceback (most recent call last):
File "<pyshell#26>", line 1, in <module>
t1[1]=3
TypeError: 'tuple' object does not support item assignment
t1=timeit.Timer('l=[1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,
3,4,5,6,7,8]')
t11=t1.timeit()
print ‘List creating time ‘,t11, ' \n'
t=tuple( range(9000))
l=range(9000)
Tuple
OUTPUT:
Esempio:
>>>mydic={ } # dizionario vuoto
>>>mydic={1: ’Hello’, ‘due’: ’World’} # dizionario con due elementi
>>>mydic[1]
‘hello’
Dictionary
Le chiavi in Python sono univoche e sono inoltre case-sensitive.
I dati contenuti in un dizionario possono essere eterogenei.
Esempio:
>>>mydic={‘a’:’Ciao’,’b’:’Mondo’}
>>> mydic[a]=‘CIAO’;
>>> mydic
{1: 'CIAO', 'due': 'world'}
>>> mydic[‘c’] # Errore la chiave non è presente
Traceback (most recent call last):
File "<pyshell#73>", line 1, in <module>
mydic['c']
KeyError: 'c’
>>>(mydic.key(), mydic.value())
([1, 'due'], ['CIAO', 'world'])
Esempio:
>>> mydic ={1:’Hello’,2:’World’ }
>>> mydic.update({3:’Ciao’}) # aggiunta tramite il metodo update
>>> mydic[4]=‘Mondo’ # aggiunta di un item
>>> mydic[2]=‘world’ # modifica di un item
>>> mydic
{1: 'Hello', 2: 'World', 3: 'Ciao', 4: 'Mondo'}
Dictionary
• Eliminazione:
Tramite cancellazione di un elemento o eliminazione dell’intero contenuto di un
dizionario. I metodi preposti:
- clear()
- pop(k[,d])
- popitem()
Esempio:
>>> mydic ={1:’Mon’,2:’Tue’,3:’Wed’,4:’Thu’,5:’Fri’,6:’Sat’,7:’Sun’}
>>>item= mydic.popitem() # popitem
>>> mydic
{2: 'Tue', 3: 'Wed', 4: 'Thu', 5: 'Fri', 6: 'Sat', 7: 'Sun'}
>>>item= mydic.pop(3) # pop
{2: 'Tue', 4: 'Thu', 5: 'Fri', 6: 'Sat', 7: 'Sun'}
Dictionary
>>>del mydic[4] #del
>>> mydic
{2: 'Tue', 5: 'Fri', 6: 'Sat', 7: 'Sun'}
>>> mydic.clear() #clear
>>> mydic
{}
• Altri metodi:
-get(k[,d])
-has_key(k)
-items()
Esempio:
>>> mydic ={1:’Mon’,2:’Tue’,3:’Wed’,4:’Thu’,5:’Fri’,6:’Sat’,7:’Sun’}
>>> mydic.has_key(8)
False
Dictionary
>>> mydic.get(7)
'Sun‘
>>> mydic.items()
[(1, 'Mon'), (2, 'Tue'), (3, 'Wed'), (4, 'Thu'), (5, 'Fri'), (6, 'Sat'), (7, 'Sun')]
#Tempi di Calcolo
Prodotto per uno scalare list: 467.861930815 microsec
Prodotto per uno scalare dict: 22.1639234568 microsec
Esempio
#OUTPUT
1 a 1a
2 b 2b
DIZIONARI DIZIONARI
>>> a={1:’a’,2:’b’} >>> a={1:’a’,2:’b’}
>>> for el in a: >>> for el in (1,2,3):
print el print a.get(el)
1 a
2 b
None
Iteratori
Per ciclare sugli oggetti di un array (lista o tupla o stringa; in generale (containers))
si utilizza il ciclo for.
Il ciclo for per operare all’interno degli elementi del containers utilizza un
oggetto detto iteratore.
L’oggetto iteratore ha le caratteristiche necessarie per muoversi nel contenitore:
1. possiede una funzione (metodo next()) che restituisce il primo dato disponibile
nel contenitore
1. lancia automaticamente l'eccezione quando non ci sono più dati nel contenitore:
StopIteration
Infatti:
>>> a=[1,2,3]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__',
'__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__‘
, '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__',
'__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append‘
, 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Iteratori
>>> my_iter=a.__iter__()
>>> dir(my_iter)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__',
'__init__', '__iter__', '__length_hint__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', 'next']
>>>try:
while(1):
print my_iter.next()
except:
print 'Stop iteration‘
>>>1
>>>2
>>>3
>>>Stop iteration
usando questi oggetti è possibile implementare un ciclo for più performante soprattutto
a livello di memoria quando il dominio su cui si vuole ciclare è molto grande (xrange)
range e xrange
Come visto negli esempi del corso range restituisce una lista di
elementi su cui ciclare.
def NameFunction(arg1,arg2,…,argN):
La keyword def è seguita dal nome della funzione e dalla lista dei
suoi argomenti.
Al prototipo della funzione segue il corpo della definizione.
Funzioni: Definizione
E’ possibile aggiungere una stringa di documentazione antecedente il corpo
della funzione per spiegare l’utilizzo della funzione e i parametri:
docstrings.
Esempio:
def stampa(stringa): Prototipo della funzione
"""La funzione stampa stampa a video la stringa stringa """ Docstring
print stringa Corpo della funzione
help(stampa)
stampa(‘Ciao’) Chiamata della funzione
Output
Help on function stampa in module __main__:
stampa(stringa)
La funzione stampa stampa a video la stringa stringa.
Ciao
Funzioni: def statement
Lo statement def è uno statement esecutivo a tutti gli effetti.
Quando viene eseguito crea una nuova function object e le
assegna un nome.
In Python è perfettamente legale dichiarare una funzione
incapsulata in altri statements.
Esempio: dyn_def.py
Esempio ordina.py
def insertion_sort(a):
for i in range(1,len(a)):
val=a[i]
j=i-1
while (j>=0 and a[j]>val):
a[j+1]=a[j]
j=j-1
a[j+1]=val
return a
Argomenti di una Funzione
def bubble_sort(a):
n=len(a)
while(n>0):
for i in range(0,n-1):
if(a[i]>a[i+1]):
tmp=a[i]
a[i]=a[i+1]
a[i+1]=tmp
n=n-1
return a
Argomenti di una Funzione
def ordina(a,method='bubble',copy=False):
if method=='bubble':
if copy==False:
b=bubble_sort(a)
else:
b=bubble_sort(a[:])
elif method==‘insert’:
if copy==False:
b=insertion_sort(a)
else:
b=insertion_sort(a[:])
else:
print “No valid method”
return b
Argomenti di una Funzione
v=[5,8,2,4,6,7,2,7,1,9,8]; print "v=",v
l=ordina(v,copy=True); print "l=",l; print "v=",v
l2=ordina(v); print "l2=",l2; print "v=",v
l3=ordina(v,copy=True,method=‘insert’); print "l3=",l3
Output:
v= [5, 8, 2, 4, 6, 7, 2, 7, 1, 9, 8]
l= [1, 2, 2, 4, 5, 6, 7, 7, 8, 8, 9]
v= [5, 8, 2, 4, 6, 7, 2, 7, 1, 9, 8]
l2= [1, 2, 2, 4, 5, 6, 7, 7, 8, 8, 9]
v= [1, 2, 2, 4, 5, 6, 7, 7, 8, 8, 9]
l3= [1, 2, 2, 4, 5, 6, 7, 7, 8, 8, 9]
Argomenti di una Funzione
Python consente di utilizzare come parametro di funzione una
lista di lunghezza variabile di argomenti. Un asterisco *
preposto al nome del parametro indica una lista di argomenti
di lunghezza variabile.
def func_var_arg(a,b,c,…,*args):
>>min_max_average(2)
Media 2.0
Min 2
Max 2
Argomenti di una Funzione
def func_var_arg(a,b,c,…,**args):
Output
function(3)
3
{}
>>function(3,b=2,c=4)
3
{‘c’:4,’b’:2}
Argomenti di una Funzione
Python permette di utilizzare una funzione come argomento di
un’altra funzione. Questa situazione è abbastanza tipica. Data
una funzione f(x) è necessaria una funzione per:
• Calcolare gli zeri di f(x)
• Calcolare l’integrale di f(x) in [a,b]
• Calcolare un’approssimazione della derivata prima
• Etc
def diff2(f,x,h=1e-6):
r=(f(x-h)-2*f(x)+f(x+h))/float(h*h)
return r
if __name__== ‘__main__’:
print “Diff2 di x^3 per x=“, 3, “ ”, diff2(f,3)
print “Diff2 di sin(x) per x=“, pi,” “, diff2(sin,pi)
Output
Diff2 di x^3 per x=3 18.001600210482138
Diff2 di sin(x) per x=pi 0.0
Argomenti di una funzione
Le funzioni in Python sono strutture molto flessibili: sono oggetti a
tutti gli effetti. Questo consente a una funzione di essere
argomento di un’altra funzione, return value, di essere assegnata ad
una variabile etc.
Esempio: Output
def f1(arg):
a=f1
print “Sono la funzione 1”
k=a(2)
if (arg): Sono la funzione 1
def f2(x):
print “Sono la funzione 2” xx=k(3)
Sono la funzione 2
print “x-value”, x x-value 3
return x
return f2 print “xx value “, xx
xx value 3
else: return None
Return Value
La keyword return permette di specificare dei valori di
ritorno di una funzione al programma chiamante.
In Python è possibile specificare più parametri di
ritorno.
Output:
Esempio: m=2, n=3
print “Prima m=“,m,“ n=“,n
def swap(a,b): Prima m=2 n=3
tmp=b swap(m,n)
b=a print “Dopo m=“,m,“ n=“,n
a=tmp Dopo m=2 n=3
Return Value
Esempio: Output:
def swap(a,b): m=2, n=3
tmp=b print “Prima m=“,m,“ n=“,n
Prima m=2 n=3
b=a
a=tmp m,n=swap(m,n)
return a,b print “Dopo m=“,m,“n=“,n
Dopo m=3 n=2
Scoping di Variabili
Output:
Inserisci un numero: 5
Inside function: x è uguale a 25
Outside function: x è uguale a 5
Scoping di Variabili
ESEMPIO
>>>val=4
>>> if (val>5):
def func3(stringa):
print 'Sono la funzione func3',stringa+str(3)
else:
def func1(stringa):
def func2(stringa):
print 'Sono la funzione func2',stringa+str(2)
print 'Sono la funzione func1', stringa+str(1)
func2(stringa)
Scoping di variabile
>>> func3()
Traceback (most recent call last):
File "<pyshell#195>", line 1, in <module>
func3()
NameError: name 'func3' is not defined
>>> func1('Ciao')
Sono la funzione func1 Ciao1
Sono la funzione func2 Ciao2
>>> func2('Ciao')
Traceback (most recent call last):
File "<pyshell#197>", line 1, in <module>
func2('Ciao')
NameError: name 'func2' is not defined
Scoping di Variabili
Il nome di una variabile globale può essere sovrascritto da una variabile
locale. Per evitare ambiguità è utile fare ricorso allo statement global con
la sintassi global var1[,var2[,…,varN[.
Esempio
globalVar=‘abc’ globalVar=‘abc’
def stampa(): def stampa():
global globalVar
globalVar =‘def’ globalVar=‘def’
print ‘Inside stampa()’, globalVar print ‘Inside stampa()’,globalVar
print ‘Outside globalVar’, globalVar
print ‘Outside gg:’, globalVar
Output Output
Inside stampa() def Inside stampa() def
Outside gg: abc Outside gg: def
Scoping di Variabili
NOTA1:
Il caricamento di un modulo avviene tramite la keyword import.
Esistono però due modalità differenti:
import module
from module import
Esempio:
import os from os import *
os.path.basename(os.getcwd()) path.basename(getcwd())
‘Python25’ ‘Python25’
Scoping di Variabili
NOTA2:
La funzione locals() e la funzione globals() restituiscono
rispettivamente un dizionario con le variabili locali e globali
dello scope corrente.
Scoping di Variabili
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None,
'__package__': None}
>>> import math
>>> globals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None,
'math': <module 'math' (built-in)>, '__package__': None}
>>> from math import *
>>> globals()
{'pow': <built-in function pow>, 'fsum': <built-in function fsum>, 'cosh': <built-in function cosh>,
'ldexp': <built-in function ldexp>, 'hypot': <built-in function hypot>, 'acosh': <built-in function
acosh>, 'tan': <built-in function tan>, 'asin': <built-in function asin>, 'isnan': <built-in function
isnan>, 'log': <built-in function log>, 'fabs': <built-in function fabs>, 'floor': <built-in function
floor>, 'atanh': <built-in function atanh>, 'sqrt': <built-in function sqrt>, '__package__': None,
'frexp': <built-in function frexp>, 'factorial': <built-in function factorial>, 'degrees': <built-in
function degrees>, 'pi': 3.141592653589793, 'log10': <built-in function log10>, '__doc__': None,
'math': <module 'math' (built-in)>, 'asinh': <built-in function asinh>, 'fmod': <built-in function
function gamma>}
Scoping di Variabili
>>> myf()
{'a': 3, 'x': 5}
Lambda Function
Python permette la creazione di funzioni inline anonime, tramite la keyword
lambda, con la sintassi:
lambda <args> : <expression>
equivalente ad un funzione con argomenti args e con return-value expression.
Sebbene Python non sia un linguaggio funzionale, l’utilizzo delle lambda
function congiuntamente all’utilizzo di alcune funzioni built-in permette la
creazione di costrutti tipici del paradigma funzionale.
Esempio:
def power(x): return x**2
print “f:” , power(4)
g=lambda x: x**2
print “g:”, g(4)
Lambda Function
Le funzioni built-in:
• filter(function or None, sequence) -> list
• map(function, sequence,[sequence,…]) -> list
• reduce(function, sequence[, initial]) -> value
Sono utilizzate spesso in congiunzione con le funzioni lambda.
Lambda Function
>>> l=range(10)
>>> filter(lambda x: x < 3, l)
[0,1,2]
>>>def f(x):
if(x<3): return True
>>>filter(f,l)
Lambda Function
>>>a=range(10); print a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>b=map(lambda x:x*3,a); print a
[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
Lambda Function
>>>a=range(10); print a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>b=reduce(lambda x,y: x+y,a); print b
45
>>>c=sum(a); print c
45
Lambda Function
Esempio: Prodotto Matrice-Vettore:
-Metodo 1:
def prod_mat_vect1(m,v,dim,dim2):
res=[0 for i in xrange (len(v))]
for i in xrange(dim):
for j in xrange(dim2):
res[i]+=m[i][j]*v[j]
return res
Lambda Function
-Metodo 2: eliminazione ciclo colonne
def prod_mat_vect2(m,v,dim):
res=[0 for i in xrange(dim)]
for i in xrange(dim):
res[i]=reduce(lambda x,y: x+y,map(lambda x,y: x*y, m[i][:], v))
return res
Lambda Function
def factorial(n):
if n==0 or n==1:
return 1
else:
return n*factorial(n-1)
factorial(5)
Contenuti:
• Attributi:
- closed: valore bool che indica se il file è aperto o chiuso
- name: nome del file
- mode: modalità di utilizzo del file.
Metodi Object File
try: # Esempio file_methods.py
f=open(‘file_prova.txt','w+')
for i in xrange(20):
f.write("Riga "+str(i)+'\n')
f.flush()
f.seek(0)
print f.read()
f.seek(0)
f.truncate(10)
l=f.readlines()
print l
print “Riga 100”, l[100]
except IOError:
print "Impossibile trovare il file specificato !“ Errore out of range!!
except IndexError,e:
print “Errore out of range: ” ,e
finally:
Viene eseguito finally
f.close()
Metodi Object File
Esempio test_lettura.py (efficienza nella lettura di un file di dati)
import timeit
def read_m1(name):
f=open(name)
while 1:
lines=f.readlines(10000)
if not lines:
break
for line in lines:
pass
f.close()
Metodi Object File
def read_m2(name):
f=open(name)
while 1:
line=f.readline()
if not line:
break
pass
f.close()
Metodi Object File
def read_m3(name):
f=open(name,’r’)
l=f.read()
for i in l:
pass
name=['1mb.test','5mb.test‘,’10mb.test’,’100mb.test’]
out=open('time_read.txt','a')
Metodi Object File
for i in name:
t=timeit.Timer('read_m1(i)','from __main__ import read_m1,name,i')
z=t.timeit(100)
out.write('Tempo di lettura m1 '+ str(i)+': '+str(z)+'\n')
OUTPUT
Tempo di lettura m1 1mb.test: 1.41886830661
Tempo di lettura m2 1mb.test: 1.75900309599
Tempo di lettura m3 1mb.test: 5.46952516591
Tempo di lettura m1 5mb.test: 7.76999695747
Tempo di lettura m2 5mb.test: 10.1169012491
Tempo di lettura m3 5mb.test: 32.3493717795
• Modulo os.path
Il modulo os.path dispone delle più comuni funzionalità per la
manipolazione del pathname. Tra cui le principali:
Informazioni sul pathname:
- abspath( string ) → string
- basename( string ) →string
- dirname ( string ) →string
File Handling
Esempi:
>>>os.path.abspath(‘Python’)
'C:\\Programs\\Python‘
>>>os.path.basename('C:\Programs\Python\‘ )
‘Python’
>>>os.path.dirname('C:\Programs\Python\‘)
‘C:\\Programs’
File Handling
Interrogazioni pathname:
Esempio:
>>>os.path.isdir(‘C:\Program\Python\ciao.txt’)
False
File Handling
Manipolazione del pathname:
- normcase ( string ) → string
- split ( string) → (head,tail)
- join ( a, *p ) → string
Esempio:
>>>os.path.join(‘C’,’Programs’,’ciao.txt’)
‘C\\Programs\\ciao.txt’
File Handling
Esempio:
>>> k=os.path.getatime('C:\Programs\tempi_range.txt')
>>> time.gmtime(k)
(2009, 4, 3, 10, 17, 40, 4, 93, 0)
Modulo os
Modulo os
Il modulo os contiene molte funzioni per la manipolazione di file,
directory, processi. L’utilizzo di questo modulo permette lo
sviluppo di applicazioni multipiattaforma garantendo la
portabilità del codice.
1file.txt
2.file.log
Modulo Glob
• glob.fnmatch.fnmatch( filename,pattern ) bool
La funzione fnmatch verifica che il filename corrisponda a
pattern. Il confronto è case-insensitive. Per un confronto case-
sensitive può essere utilizzata la funzione
glob.fnmatch.fnmatchcase
l=[]
for ffile in os.listdir(‘.’):
if glob.fnmatch.fnmatch(ffile, ‘*.txt’):
l.append(ffile)
#OPPURE
l=glob.fnmatch.filter(os.listdir(‘.’),’*.txt’)
Python per il calcolo
scientifico
Indice
• Numpy
• Creazione di un array
• Reshape & Resize
• Indexing
• Operatori Aritmetici
• ufunc
• Broadcasting
• Cenni di vettorizzazione
• Efficienza e loop
• Array Copy
• Attributi e Metodi
• I/O con Array Numpy
• Matrix
Python in ambito scientifico
Python è diventato accessibile a nuovi gruppi di utilizzatori. A dispetto della
sua semplicità è un linguaggio abbastanza potente da permettere la
gestione di applicazioni complesse
• Python ha una posizione forte nell’ambito del Computing Scientifico:
– E’ open-source!
– Ci sono significative e diffuse comunità di utenti, quindi è piuttosto
facile reperire in rete aiuto e documentazione
– Ad oggi è disponibile un esteso ecosistema di environment, di package
e di librerie scientifiche per Python ed è in rapida crescita
– Si possono scrivere codici Python che ottengono ottime performance,
grazie alla forte integrazione con prodotti altamente ottimizzati scritti
in C e Fortran (BLAS, Atlas, Lapack, Intel MKL®, …)
– E’ possibile sviluppare applicazioni parallele che usino la
comunicazione interprocesso (MPI), il multi-threading (OpenMP) ed il
GPU computing (OpenCL e CUDA)
Python in ambito scientifico
A livello mondiale è sfruttato in ambito scientifico (e non solo) in diversi
progetti:
• National Space Telescope Laboratory (Hubble Space Telescope)
• Lawrence Livermore National Laboratories (pyMPI)
• Enthought Corporation (Applicazioni Geofisiche ed Elettormagnetiche)
• Anaconda (RedHat Linux Installer)
• Google
Contenuti
Nello specifico verranno trattati:
• Principali limitazioni:
– NumPy non è supportato per lo sviluppo di applicazioni Google App
Engine, perché molte sue parti sono scritte in C
– Gli utenti di Jython – l’implementazione Java di Python – non posso
contare sul modulo NumPy: Jython gira all’interno di una Java Virtual
Machine e non può importare NumPy, perché molte sue parti sono
scritte in C
Import del modulo
• Importiamo il modulo come di consueto
Teminologia:
Con size di un array intendiamo il numero di elementi presenti in un array.
Con rank di un array si intende il numero di assi/dimensioni di un array.
Con shape di un array intendiamo le dimensioni dell’array, cioè una tupla di
interi contenente il numero di elementi per ogni dimensione, numero
VARIABILE.
L’ itemsize rappresenta la dimensione in memoria di ogni singolo elemento
dell’array.
ndarray
La definizione del ndarray numpy/core/include/numpy/ndarrayobject.h
0 1 2
P
yt
h o
nVie
w: Python View
3 4 5
6 7 8
54
Creazione di un Array
Creazione di un array
Ci sono diverse modalità per generare un array. La più semplice consiste
nell’utilizzo della funzione
array(object, dtype=None, copy=1,order=None) array
>>>import numpy as np
>>>a=np.array([1,2,3,4])
>>>lista1=[1,2,3,4]
>>>tupla=(5,6,7,8)
>>>a=np.array(lista) #from a list
>>>b=np.array(tupla) #from a tupla
>>>c=np.array([lista,tupla]) #from a list and from a tupla
>>>a.dtype
dtype('int32')
ndtype
• Ci sono 21 built-in data type che possono essere usati per creare un array.
• Numpy supporta più tipi di dato rispetto a python puro.
Type Description
bool Boolean
int Platforma integer
int8 Byte (-128,127)
int16 Integer (-32768,32767)
int32 Integer (-2147483648, 2147483647)
int64 Integer (-9223372036854775808, 9223372036854775807)
>>>dt=dtype([('Name','S3'),(‘Anni', numpy.int64)])
>>a=array([('Chiara',3),('Marco',4)],dtype=dt)
>>> a
array([('Chi', 3L), ('Mar', 4L)],
dtype=[('Name', '|S3'), ('Val', '<i8')])
>>>dt=dtype({'names':('Name','Anni','Cognome'),'formats':('S3','int64','S3')})
>>>a=array([('Chiara',3,'Bianchi'),('Marco',4,'Rossi')],dtype=dt)
>>> a
array([('Chiara', 3L, 'Bia'), ('Marco', 4L, 'Ros')],
dtype=[('Name', '|S10'), ('Anni', '<i8'), ('Cognome', '|S10')])
Dimension e shape
int nd; /* number of dimensions, also called ndim */
npy_intp *dimensions; /* size in each dimension */
La funzione
resize(new_shape, refcheck=True, order=False)
Lavora direttamente in-place e permette di modificare la forma dell’array e di
ridimensionarlo.
Resize funziona solo se l’array non è referenza o non è referenziato.
Esempio
>>>a=arange(20)
>>>a.resize(5,6) #Ok
Reshape & Resize
>>>b=a
>>>a.resize(3,3) #Error a is referenced by b
Traceback (most recent call last):
File "<pyshell#160>", line 1, in <module>
a.resize(3,3)
ValueError: cannot resize an array that has been referenced or is referencing
another array in this way. Use the resize function
Esempio
>>>a=array(range(1,9))
>>>print “Shape” , a.shape
>>>c_style=a.reshape((2,2,2),order=‘C’) #Array Method: Numpy Style
>>>f_style=reshape(a,(2,2,2),order=‘F’) #Numpy Function
>>>print “C-style “, c_style
>>>print “Fortran-style “, f_style
>>>c_style=c_style.reshape((2,4))
>>>print “Reshape c_style“, c_style
>>>f_style=f_style.reshape((2,4))
>>>print “Reshape f_style”,f_style
Reshape & Resize
OUTPUT
Shape (8,)
>>> x = np.arange(10,1,-1)
Il nuovo array:
array([10, 9, 8, 7, 6, 5, 4, 3, 2]) ➔ ha la shape dell’array di indici
A=x[np.array([3,3,2,8])] ➔ ha tipo e valori dell’array di partenza
array([7, 7, 8, 2])
>>> AA=x[np.array([[3,3],[2,8]])]
array([[7, 7],
[3, 2]])
Indexing – Slicing - Iteration
Usando una maschera booleana
>>> y
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17]])
>>> y[y>10]
array([11, 12, 13, 14, 15, 16, 17] # 1d array
36
Indexing – Slicing - Iteration
Iteration
L’iterazione sugli elementi di un array può essere effettuata in diversi modi.
Attraverso il classico ciclo for lungo gli assi dell’array:
Esempio:
>>>a=arange(9)
>>>a.shape=(3,3)
>>>for i in xrange(a.shape[0]):
for j in xrange(a.shape[1]):
a[i,j]=i+j
Il ciclo for applicato invece agli elementi di un array agisce di default sul
primo asse.
Indexing – Slicing - Iteration
Esempio:
>>>for el in a:
print el
>>>[ 0 1 2]
[ 1 2 3]
[ 2 3 4]
Esempio:
>>> for i in a.flat:
print i
012123234
L’operazione di iterazione sugli array risulta tuttavia poco efficiente computazionalmente.
Per le operazioni sugli array Python dispone di funzioni scritte in C che operano
direttamente sull’intero array…SEGUE
Operazioni numeriche su array
• Operazioni elementari con scalari:
>>> a = np.array([1, 2, 3, 4])
>>> a + 1 # somma di uno scalare
array([2, 3, 4, 5])
>>> a – 2 # sottrazione di uno scalare
array([-1, 0, 1, 2])
>>> 3*a # moltiplicazione per uno scalare
array([3, 6, 9, 12])
>>> 2**a # potenza (base scalare)
array([2, 4, 8, 16])
>>> a = np.array([1., 2., 3., 4.])
>>> a/2 # divisione per uno scalare
array([0.5, 1., 1.5, 2.])
Operatori Aritmetici
Operatori aritmetici
Gli operatori aritmetici agiscono in maniera elementwise sugli array.
Questa regola si applica sia ad operatori unari che ad operatori binari. E’ inoltre
valida per funzioni matematiche unarie (sin, cos, etc.)
>>> np.array_equal(a,b)
False Per un confronto arraywise si
usa il metodo array_equal
>>> np.array_equal(a,c)
True
Operatori logici
>>> np.logical_or(a,b)
array([True, True, True, False], dtype=bool)
>>> np.logical_and(a,b)
array([True, False, False, False], dtype=bool)
ufunc
• Numpy oltre alla definizione dell’oggetto ndarray definisce anche le
funzioni universali ufunc
• Le funzioni ufunc permettono di operare elemento- elemento ,
sull’intero array senza dover usare dei loop espliciti.
• Queste funzioni sono dei wrapper a delle funzioni del core numpy
tipicamente sviluppate in C o Fortran
>>>a=numpy.arange(100)
>>>b=numpy.cos(a)
ufunc
Esempio della funzione ufunc_loop definita nel core di Numpy
void ufunc_loop(void **args, int *dimensions, int *steps,
void *data)
{
char *input_1 = (char*)args[0];
char *input_2 = (char*)args[1];
char *output = (char*)args[2];
int i;
for (i = 0; i < dimensions[0]; ++i) {
*output = elementwise_function(*input_1, *input_2);
input_1 += steps[0];
input_2 += steps[1];
output += steps[2];
}
}
ufunc
• Ci sono più di 60 ufuncs
• Alcune ufunc sono nascoste dietro gli operatori aritmetici: i.e.
np.multiply(x,y)
è chiamata quando si effettua l’operazione a*b
• NumPy offre funzioni trigonometriche, esponenziali and logaritmiche etc
etc. Alcuni esempi:
>>> b = np.sin(a)
>>> b = np.arcsin(a)
>>> b = np.sinh(a)
>>> b = a**2.5 # power function
>>> b = np.log(a)
>>> b = np.exp(a)
>>> b = np.sqrt(a)
ufunc
• Funzione di confronto:
greater, less, equal, logical_and/_or/_xor/_nor, maximum, minimum, ...
>>> a = np.array([2,0,3,5])
>>> b = np.array([1,1,1,6])
>>> np.maximum(a,b)
array([2, 1, 3, 6])
• Visto che tutte le tipologie di operatori tra array lavorano elementwise, gli array
operandi devono avere (sempre) la stessa shape
>>> a = np.arange(4)
>>> a + np.array([1,2])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (4) (2)
• E possibile talvolta operare con array che non hanno le stesse dimensioni
c=arange(1,5)
d=array([[1,1,1,1],[2,2,2,2]])
print d, ”+”, c “= “ d+c stretch
a=arange(6)
a=a.reshape((2,1,3))
a + b = c
b=arange(8)
b=b.reshape((2,4,1))
c=a+b #OK!! Broadcastable
a=a.arange(30)
a=a.reshape((2,5,3))
b=arange(8)
b=b.reshape((2,4,1)) #No Broadcastable
Array performance
• Le funzioni Numpy sono efficienti per lavorare sugli array, ma possono lavorare
anche sugli scalari.
• Le funzioni contenute in math sono più efficienti sugli scalari rispetto alle funzioni
Numpy.
def no_loop(a):
a=a*3+1
Tempi di calcolo:
for_array on 1000 X 1000 array = 3.52 s
no_loop on 1000 X 1000 array = 0.015 s
Efficienza di Calcolo
Per la stessa motivazione le strutture dati array risultano più efficienti delle liste.
def somma_array(v1,v2):
v=v1+v2
def somma_liste(l1,l2):
l=[]
for i in xrange(len(l1)):
l.append(l1[i]+l2[i])
Tempo di calcolo:
somma_array(v1,v2) con 10^7 elementi = 0.05 s
somma_liste(l1,l2) con 10^7 elementi = 10.49 s
Cenni di vettorizzazione
I cicli for sono piuttosto lenti in Python. Uno dei vantaggi nell’utilizzo degli
array consiste nel fatto che molte operazioni possono essere svolte
evitando loop espliciti questo procedimento prende il nome di
vettorizzazione.
Esempi:
VECTORIZED VERSION SCALAR VERSION
a=arange(0,4*pi,0.1) Anziché y=zeros(len(a))
y=sin(a)*2 for i in xrange(len(a)):
y[i]=sin(a[i])*2
xk xk 1 2 xk xk 1 k=1,2,…,n-1
for i in xrange(1,len(x)-1):
x[i]=x[i-1]+2*x[i]+x[i+1]
x[1:n-1]=x[0:n-2]+2*x[1:n-1]+x[2:n]
Attributi e Metodi
L’object class array dispone di utili funzionalità implementate come propri metodi e
attributi.
Attributi:
Gli attributi della classe array forniscono informazioni sulla struttura dell’array. Si
ricordano:
• dtype tipo di dato
• flat array di (rank-1)
• itemsize e nbytes bytes usati da ogni singolo elemento e dall’intero array
• ndim numero di dimensioni dell’array
• size numero totale di elementi nell’array
• shape forma dell’array
Metodi
I metodi built-in implementano funzionalità che operano direttamente sull’array. Si
ricordano:
Attributi e Metodi
take(indices, axis=None, out=None, mode='raise')
La funzione take estrapola un sottoarray costituito dagli elementi in posizione
indices secondo l’asse axis
Esempio:
>>>a=arange(27)
>>>a.resize(3,3,3)
>>>y=a.take([0,2],axis=1)
>>>y2=a.take([0,2],axis=2)
>>>y3=a.take([0,2],axis=0)
Attributi e Metodi
choose(choices, out=None, mode='raise')
La funzione choose restituisce un array costruito dalle choices sulla base di un
filtro selettore.
compress(condition,axis=None, out=None)
La funzione compress restituisce un array di elementi che soddisfano
condition lungo l’asse axis
Attributi e Metodi
fill(value)
La funzione fill riempe l’array con il valore value.
sort(axis=-1, kind=‘quicksort’, order=None)
La funzione sort riordina inplace i valori dell’array lungo axis con il metodo
kind.
transpose(*axis)
La funzione transpose traspone gli elementi dell’array secondo la
permutazione specificata da axis.
>>> x = np.arange(4)
>>> y = np.arange(4)
>>> def f(x,y):
... return x**2+y
>>> f(x,y)
array([0, 2, 6, 12])
64
La soluzione: meshgrid
>>> x = np.arange(4)
>>> y = np.arange(4)
>>> xx, yy = np.meshgrid(x,y)
>>> xx
array([[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]])
>>> yy
array([[0, 0, 0, 0],
[1, 1, 1, 1], >>> f(xx,yy)
[2, 2, 2, 2], array([[ 0, 1, 4, 9],
[3, 3, 3, 3]]) [ 1, 2, 5, 10],
>>> def f(x,y): [ 2, 3, 6, 11],
... return x**2+y [ 3, 4, 7, 12]])
65
I/O con Array Numpy
• Si possono usare le funzioni eval e repr per scrivere e leggere in formato
ASCII
a = linspace(1, 21, 21)
a.shape = (2,10)
# ASCII format:
file = open(’tmp.dat’, ’w’)
file.write(’Here is an array a:\n’)
file.write(repr(a)) # dump string representation of a
file.close()
# load the array from file into b:
file = open(’tmp.dat’, ’r’)
file.readline() # load the first line (a comment)
b = eval(file.read())
file.close()
I/O con Array Numpy
• L’I/O su file può essere anche gestito loadtxt e savetxt
Lettura:
numpy.loadtxt(fname, dtype=<type
'float'>, comments='#', delimiter=None, converters=None, skiprows=0,
usecols=None, unpack=False, ndmin=0)
Scrittura:
numpy.savetxt(fname, X, fmt='%.18e', delimiter='
', newline='\n', header='', footer='', comments='#)
I/O con Array Numpy
• Text.txt
>>>a = loadtxt('textfile.txt',skiprows=2,usecols=range(1,5))
>>>print a
>>>b = loadtxt(‘textfile.txt’,skiprows=2,usecols=(1,-2))
>>> print b
I/O con Array Numpy
• Per lavorare con molti dati è più conveniente scrivere e leggere in formato
binario.
• Il modo più semplice è usare il modulo cPickle
#Write to File
# a1 and a2 are two arrays
import cPickle
file = open(’tmp.dat’, ’wb’)
file.write(’This is the array a1:\n’)
cPickle.dump(a1, file)
file.write(’Here is another array a2:\n’)
cPickle.dump(a2, file)
file.close()
I/O con Array Numpy
>>> np.save(‘myData.npy’,my_data)
>>> dir(linalg)
['LinAlgError', 'Tester', '__builtins__', '__doc__', '__file__', '__name__',
'__package__', '__path__', 'bench', 'cholesky', 'cond', 'det', 'eig', 'eigh',
'eigvals', 'eigvalsh', 'info', 'inv', 'lapack_lite', 'linalg', 'lstsq', 'matrix_power',
'matrix_rank', 'norm', 'pinv', 'qr', 'slogdet', 'solve', 'svd', 'tensorinv',
'tensorsolve', 'test']
linalg
Esempio:
A = np.zeros((10,10)) # arrays initialization
x = np.arange(10)/2.0
for i in range(10):
... for j in range(10):
... A[i,j] = 2.0 + float(i+1)/float(j+i+1)
b = np.dot(A, x)
y = np.linalg.solve(A, b) # A*y=b → y=x
# eigenvalues only:
>>> A_eigenvalues = np.linalg.eigvals(A)
# eigenvalues and eigenvectors:
>>> A_eigenvalues, A_eigenvectors = np.linalg.eig(A)
random
random è un altro modulo definito dentro numpy per la generazione di
numeri casuali
dir(random)
['RandomState', 'Tester', '__RandomState_ctor', '__all__', '__builtins__',
'__doc__', '__file__', '__name__', '__package__', '__path__', 'bench', 'beta',
'binomial', 'bytes', 'chisquare', 'dirichlet', 'exponential', 'f', 'gamma',
'geometric', 'get_state', 'gumbel', 'hypergeometric', 'info', 'laplace', 'logistic',
'lognormal', 'logseries', 'mtrand', 'multinomial', 'multivariate_normal',
'negative_binomial', 'noncentral_chisquare', 'noncentral_f', 'normal', 'np',
'pareto', 'permutation', 'poisson', 'power', 'rand', 'randint', 'randn', 'random',
'random_integers', 'random_sample', 'ranf', 'rayleigh', 'sample', 'seed',
'set_state', 'shuffle', 'standard_cauchy', 'standard_exponential',
'standard_gamma', 'standard_normal', 'standard_t', 'test', 'triangular',
'uniform', 'vonmises', 'wald', 'weibull', 'zipf']
random
Generare un array di numeri casuali usando il modulo standard numpy è
inefficiente, meglio usare il modulo numpy.random
>>> np.random.seed(100)
>>> x = np.random.random(4)
array([ 0.89132195, 0.20920212, 0.18532822,
0.10837689])
>>> y = np.random.uniform(1, 1, n) # n uniform
numbers in interval (1,1)
Distribuzione normale
>>> mean = 0.0; stdev = 1.0
>>> u = np.random.normal(mean, stdev, n)
Scipy
Introduzione a SciPy
Introduzione
2
Introduzione
3
Warning
• Questo modulo del corso “Python for Computational Science” non vuole
essere una introduzione al calcolo numerico, cosa che è al di la dei nostri
compiti istituzionali.
4
La struttura di SciPy
• Scipy è composto da sotto-moduli specifici per tipologia di applicazione;
ad oggi la lista dei sotto-moduli disponibili è la seguente:
Sub-module Task
scipy.cluster Vector quantization / Kmeans
scipy.constants Physical and mathematical constants
scipy.fftpack Fourier transform
scipy.integrate Integration routines
scipy.interpolate Interpolation
scipy.io Data input and output
scipy.linalg Linear algebra routines
scipy.ndimage n-dimensional image package
5
La struttura di SciPy
Sub-module Task
scipy.odr Orthogonal distance regression
scipy.optimize Optimization
scipy.signal Signal processing
scipy.sparse Sparse matrices
scipy.spatial Spatial data structures and algorithms
scipy.special Any special mathematical functions
scipy.stats Statistics
7
Funzioni speciali:
il modulo sciyy.special
• Il modulo contiene una vasta scelta di funzioni speciali
• Il suo help è molto bel fatto ed contiene un elenco completo delle funzioni
disponibili, raggruppate per tipologia: è un ottimo riferimento per vedere
cosa è presente nel modulo e come utilizzarlo
10
Linear algebra:
calcolo dell’inversa
11
Linear algebra:
singular-value decomposition
La singular-value decomposition di una matrice A consiste nel calcolo di 2
matrici unitarie U e V ed di un array s di valori singolari (reali e non negativi),
tali che A = USV, in cui S è la matrice diagonale di elementi diagonali s
>>> s = np.diag(spec)
>>> svd = u.dot(s).dot(v)
>>> np.allclose(svd,a)
True NB: se il calcolo non converge,
è generato un LinAlgError
Sono disponibili anche altre decomposizioni standard: QR, LU, Cholesky, Schur 12
Linear algebra:
soluzione di un sistema lineare
Data una matrice A (n,m) ed un vettore b (n), calcolare il vettore x (n) tale
che Ax=b
13
Ottimizzazione e fit:
scipy.optimize
In generale, l’ottimizzazione consiste nella ricerca di una soluzione numerica
a un problema di minimizzazione o nel calcolo degli zeri di una funzione
15
Ricerca del minimo assoluto
• Un possibile problema di questo approccio è che, se la funzione presenta
minimi locali, l’algoritmo può giungere ad uno di questi ultimi, invece che
al minimo assoluto, per certe scelte dello starting point della discesa
• In caso di griglia con molti punti, questo metodo può diventare costoso
• La funzione optimize.anneal è una soluzione alternativa al problema,
che usa il metodo del simulated annealing
• Esistono diversi algoritmi, non compresi in SciPy, che risultano più
efficienti per differenti classi di problemi di ottimizzazione globale; in
caso di necessità, segnaliamo OpenOpt, IPOPT, PyGMO e PyEvolve 17
Ricerca degli zeri di una funzione
• La funzione scipy.optimize.fsolve consente di
trovare lo zero di una funzione, ovvero una
soluzione per l’equazione f(x) = 0
• Per semplicità utilizziamo la funzione vista per la
ricerca del minimo assoluto
>>> xd = np.linspace(-10,10,40)
>>> yd = f(xd) + np.random.randn(xd.size)
19
Fitting di una curva
• La forma funzionale con cui fittare il campione evidentemente è ax2 + bsin(x)
• Usiamo il non linear least square fit per determinare il valore ottimale dei
parametri a e b
20
Fitting di una curva
Visualizziamo tutto quanto abbiamo trovato sulla funzione f(x) in un
unico plot
21
scipy.stats: istogramma e PDF
• scipy.stats contiene un gran numero di strumenti per descrivere campioni
statistici, per lavorare con distribuzioni di probabilità - continue e discrete - e
per eseguire diverse tipologie di test statistici
23
scipy.stats: istogramma e PDF
24
Maximum-likelihood fit
Se il campione proviene da un processo random appartenente ad una data
famiglia (i processi gaussiani, nel nostro caso), possiamo usare il maximum-
likelihood fit del nostro campione per stimare i parametri della distribuzione
sottostante
25
Percentili
• La mediana di un campione è il numero m tale che il 50% degli elementi
del campione sono più piccoli di m ed il restante 50% più grandi di m
• La mediana di un campione è chiamato anche percentile 50 perché il 50
degli elementi del campione ha un valore inferiore
• Il percentile è un estimatore della densità di probabilità cumulativa (CDF)
>>> a = np.random.normal(0,1,size=100)
>>> b = np.random.normal(1,1,size=80) # diverso da a
>>> stats.ttest_ind(a,b)
(array(-7.676065328644207), 1.0441890418905031e-12)
>>> stats.ttest_ind(a,b)
(array(-0.7067713387921485), 0.48063276502750174)
27
Introduzione a SciPy:
esercizi proposti
Interpolazione:
scipy.interpolate
• Il modulo contiene funzionalità per il fitting di una funzione (1D e 2D) a
partire da dati esperimentali e per la successiva valutazione della
funzione in punti in cui il dato sperimentale è mancante
>>> t = np.linspace(0,1,10)
>>> noise = 0.1 * (2 * np.random.random(10) -1)
>>> measures = np.sin(2* np.pi * t) + noise
29
Interpolazione 1D lineare e cubica
Eseguiamo un’interpolazione sia lineare che cubica dei dati sperimentali, per
poi confrontarle con i dati misurati in un plot
30
Interpolazione 1D:
plot per confronto con i dati
Costruiamo il plot per il confronto tra le curve calcolate e i dati sperimentali
di partenza
31
… Interpolazione 1D:
plot per confronto con i dati
32
scipy.integrate:
integrazione numerica
scipy.integrate.quad() è la più generica funzione per l’integrazione
numerica 1D presente in SciPy
• Oltre al semplice integrale definito, quad sa fare molte altre cose (cfr. help)
• dblquad e tplquad sono usate nel caso 2D e 3D rispettivamente
• In scipy.integrate sono disponibili anche altri schemi d’integrazione
numerica (cfr. fixed_quad, quadrature, romberg) 33
scipy.integrate: ODE
34
scipy.integrate: ODE
dy
= -2y con t Î [0,4] e y(0) =1
dt
• Iniziamo con lo scrivere in Python la funzione che calcola la derivata
rispetto al tempo della funzione y
35
scipy.integrate: ODE
36
scipy.integrate: ODE
37
scipy.integrate: ODE
x¢¢ + 2ew0 x¢ + w x = 0 2
0
k c
in cui w =2
e e=
2mw 0
0
m
con k costante elastica della molla, m massa del oscillatore e c coefficiente
di damping
38
... scipy.integrate: ODE …
ì dx
ïï = p
dt
í
ï dp = -2ew p- w 2 x
ïî dt 0 0
# condizione iniziale
>>> y0 = [1.0, 0.0]
# coordinate temporali in cui trovare la soluzione
>>> t = np.linspace(0,10,1000)
>>> wo = 2*np.pi
>>> from scipy.integrate import odeint
# risolviamo ls ODE per 4 valori diversi di eps
>>> y1 = odeint(dy,y0,t,args=(0.0,w0)) # undamped
>>> y2 = odeint(dy,y0,t,args=(0.2,w0)) # under damped
>>> y3 = odeint(dy,y0,t,args=(1.0,w0)) # critial damping
>>> y4 = odeint(dy,y0,t,args=(5.0,w0)) # over damped
40
scipy.integrate: ODE
41
scipy.integrate: ODE
42
Fast Fourier trasform: scipy.fftpack
43
Fast Fourier trasform: scipy.fftpack
44
Fast Fourier trasform: scipy.fftpack
45
Fast Fourier trasform: scipy.fftpack
46
Matplotlib
Indice
• Modulo Pylab
• Introduzione a Pylab
• Comandi di base
• Figure
• Plot e Subplot
• Axes
• Line2D Properties
• Gestione del testo
• Esempi: diagrammi a barre, pie plot, scatterplot, istogrammi,
meshgrid, contourplot,
Matplotlib: Modulo Pylab
“Matplotlib tries to make easy things easy and hard things possible”
John Hunting
subplot(2,3,5)
Plot e Subplot
Creating subplot - pylab
subplot(2, 1, 1)
plot(x, x ** 2, 'b--')
subplot(2, 1, 2)
plot(x, cos(2*pi*x), 'r.')
subplots_adjust(hspace = 0.5)
show()
Plot e Subplot
Creating subplot - OO
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 8*np.pi,
num=40)
f=plt.figure()
ax=f.add_subplot(2,1,1)
ax.plot(x, np.sin(x))
ax2=f.add_subplot(2,1,2)
ax2.plot(x, np.arctan(x))
f.subplots_adjust(
left=0.13, right=0.97,
top=0.97, bottom=0.10,
wspace=0.2, hspace=0.4)
plt.show()
Axes
L’oggetto axes() permette la gestione degli assi e si comporta in maniera
simile a subplot.
axes() equivale a subplot(111)
axes([left,bottom, width, height]) posiziona e dimensiona il grafico secondo la
lista di parametri passati come argomento.
Alcuni metodi
axis([xmin,xmax,ymin,ymax])
grid()
xticks(location,label)
legend([list_lines],[list_label], loc,
[text_prop])
Axes
Esempio histoaxis.py
import numpy as np
import matplotlib.pyplot as plt
x = np.random.randn(1000)
y = np.random.randn(1000)
axscatter = plt.axes([0.1,0.1,0.65,0.65])
axhistx = plt.axes([0.1,0.77,0.65,0.2])
axhisty = plt.axes([0.77,0.1,0.2,0.65])
axscatter.scatter(x, y)
plt.draw()
binwidth = 0.25
xymax = max( [max(np.fabs(x)),
max(np.fabs(y))] )
lim = ( int(xymax/binwidth) + 1) * binwidth
bins = np.arange(-lim, lim + binwidth, binwidth)
axhistx.hist(x, bins=bins)
plt.draw()
axhisty.hist(y, bins=bins, orientation='horizontal')
plt.draw()
plt.show()
Axes
Esempio doppio.py
import numpy as np
from matplotlib import pyplot as plt
x=[1,2,3,4,5,6,7]
y=[10,20,40,50,10,7,10]
y2=[4,10,3,4,3,10,10]
f=plt.figure()
ax=f.add_axes([0.1,0.55,0.7,0.4])
l1,=ax.plot(x,y,'r--',marker='o')
l2,=ax.plot(x,y2,marker='s',color='green',linestyle='-.')
ax.set_xticks(x)
ax.set_xticklabels(['Jan','Feb','Mar','Apr','May','Jun',
'Jul'])
ax.legend([l1,l2],['sun','rain'])
bx=ax.twiny()
bx.set_xticks(x)
ax2=f.add_axes([0.1,0.1,0.7,0.4])
ax2.plot(np.arange(10),np.arange(10),label='small')
ax2.legend(loc=2)
by=ax2.twinx()
by.plot(np.arange(10),np.exp(np.arange(10)),'r',label='big')
by.legend()
plt.show()
Line2D Properties
L’oggetto linea ha diversi attributi: è possibile modificare le dimensioni, lo stile, il
colore etc. La funzione:
setp(*args, **kwargs)
permette di cambiare tali attributi.
In alternativa è possibile modificare gli attributi tramite i metodi dell’oggetto line2D.
Tra gli attributi ricordiamo:
• color ‘b’, ‘r’, ‘g’, ‘y’, ‘ k’, ‘w’’, ‘c’, ’m’
• linewidth float
• linestyle ‘’, ’-’, ’- -’, ’:’, ‘.-’
• label stringa
• marker ‘.’, ‘o’, ‘D’, ‘^’, ‘s’, ‘*’, ‘+’, ‘h’
• markersize float
• markerfacecolor color
Line2D Properties
x=np.arange(0,np.pi,0.1)
np.plot(x,sin(x),marker='o',color='r',
markerfacecolor='b',label='sin(x)')
np.legend()
Line2D Properties
Creating subplot-- OO
Esempio sale.py
import numpy as np
from matplotlib import pyplot as plt
x=np.arange(0,100,10)
y=2.0*np.sqrt(x)
f=plt.figure()
ax=f.add_subplot(111)
line,=ax.plot(x,y)
line.set_color('r')
line.set_linestyle('--')
line.set_marker('s')
plt.setp(line,markeredgecolor='green',
markerfacecolor='b',markeredgewidth=3)
line.set_markersize(15)
plt.show()
Line2D Properties
Creating Multi-line plot
Creating subplot-- pylab
t=np.arange(0,5,0.05)
f=2*np.pi*np.sin(2*np.pi*t)
f2=np.sin(2*np.pi*t)*np.exp(-2*t)
plt.plot(t,f,'g--o',t,f2,'r:s‘)
hold(True)
f3=2*np.pi*np.sin(2*pi*t)*np.cos(2*pi*t)
plt.plot(t,f3,'c-.D',label='f3')
plt.legend(('f1','f2‘,’f3’))
plt.show()
Line2D Properties
Creating Multi-line plot
Creating subplot-- OO
Esempio crescedecresce.py
import numpy as np
from matplotlib import pyplot as plt
x=np.arange(0,100,10)
y1=2.0*np.sqrt(x);
y2=3.0*x**(1.0/3.0)
y3=4.0*x+3.0*x**2
y4=5.0*x-2.0*x**2
f=plt.figure()
ax=f.add_subplot(111)
line1,=ax.plot(x,y1,'r--')
line2,=ax.plot(x,y2,'b-.')
line3,line4=ax.plot(x,y3,x,y4)
line3.set_color('g')
line4.set_color('y')
ax.legend([line2,line3,line4],['line2','line3','line4‘])
plt.show()
Gestione del testo
x=[9,10,13,12,11,10,9,8,45,11,12,10,9,
11,10,13,9]
plt.plot(x,label='myfunc')
plt.legend()
plt.title('Mytitle')
plt.ylabel('y',fontsize='medium',color='r')
plt.xlabel('x',fontsize='x-large',color='b',position=(0.3,1))
plt.text(4,20,'mytext', color='g',fontsize='medium')
plt.annotate('annotate',xy=(8,45),xytext=(10,
35),arrowprops=dict(facecolor='black',shrink=0.05))
Images File
delta = 0.5
x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = ml.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = ml.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 10
levels = np.arange(-2.0, 1.601, 0.4)
Contour plot
plt.figure(facecolor="w")
plt.subplot(221)
plt.imshow(Z,origin= 'lower')
plt.subplot(222,axisbg="w")
l= plt.contourf(Z,levels,origin='lower')
plt.colorbar(l)
plt.subplot(223,axisbg="w")
l= plt.contour(Z, levels,origin= 'lower',linewidths=2)
plt.clabel(l,inline=1, fmt='%1.1f',fonsize=14)
plt.show()
Output
Esempio:
import timeit
def test_func():
a=[]
for el in xrange(1000000): a.append(el)
if __name__==‘__main__’:
print timeit.Timer(‘for el in range(10000000):pass’).timeit(1), ‘s’
print timeit.Timer(‘for el in xarange(10000000):pass’).timeit(1), ‘s’
print timeit.Timer(‘test_func()’, ‘from __main__ import
test_func()’).timeit() ,’s’
Timing your code
0.334960419911 s
0.947776416355 s
0.439117697007 s
import cProfile
def test():
lista=[]
for el in xrange(1000000):
lista.append[el]
if __name__==‘__main__’:
cProfile.run(‘test_func()’)
Timing your code
OUTPUT
1000003 function calls in 1.383 CPU seconds
Speed
(CPU TIME)
• Fortran
• Pensato per il calcolo scientifico
• E’ veloce
• Le performance sono il suo punto di forza
Python vs Fortran
x y z
-0.930730079412 -2.5837626746 -1.54168368133
0.242648096556 -0.0356080560781 1.64592869632
1.08469025095 -0.0499861074276 0.850168034143
0.904693997768 0.331774955996 -0.435462229263
-0.30666600039 0.502104683611 -0.147720257532
0.67879008187 0.594205526229 -2.76854972969
0.346956345057 0.64044334422 -0.397530419261
-0.415357107828 0.431902374758 -0.96024517464
-0.0423741085785 0.97632569202 1.13665523717
-0.0890995975459 -0.0170642871372 -0.209950709345
Python vs Fortran
import sys
def read_file_short(file_name):
with open(file_name) as fobj:
next(fobj)
return (tuple(float(entry) for entry in line.split()) for line in fobj)
if __name__=='__main__':
if (len(sys.argv)>1):
dim=sys.argv[1]
print find_intersection('value_'+dim+'_0.txt', 'value_'+dim+'_1.txt')
Python vs Fortran
Lettura dei dati
subroutine read_data(file_name, data_array, line, row)
implicit none
integer,intent(in)::line
integer,intent(in)::row
integer::status
integer::l
double precision, dimension(line,row)::data_array
character(len=20),intent(in)::file_name
Character(len=100)::dummy
open(unit=99,file=file_name,status='old',action='read')
read(99,*,iostat=status) dummy
do l=1,line
read(99,*,iostat=status) data_array(l,1), data_array(l,2),
data_array(l,3)
if (status /=0) exit
enddo
close(99)
end subroutine read_data
Python vs Fortran
Funzione di intersezione
subroutine find_intersection(data_array1,data_array2,line1,line2,row)
implicit none
integer, intent(in)::line1,line2,row
integer::status,counter=0,l1,l2,r,matches
double precision, intent(in),dimension(line1,row)::data_array1
double precision, intent(in),dimension(line2,row)::data_array2
double precision, allocatable, dimension(:,:):: found_temp
double precision, allocatable, dimension(:,:):: found
allocate(found_temp(min(line1,line2),row),stat=status)
do l1=1,line1
do l2=1,line2
matches=0
do r=1,row
if(data_array1(l1,r)==data_array2(l2,r)) then
matches=matches+1
endif
enddo
if (matches==3) then
counter=counter+1
do r=1,row
found_temp(counter,row) =data_array1(l1,r)
enddo
endif
enddo
Python vs Fortran
enddo
allocate (found(counter,row),stat=status)
if(status /=0) then
write(*,*),'Error allocating'
end if
do l1=1,counter
do r=1,row
found(l1,r)=found_temp(l1,r)
end do
end do
write(*,*) counter
end subroutine find_intersection
Python vs Fortran
Programma chiamante
program common_coord
implicit none
integer::number_of_line1=0
integer::number_of_line2=0
integer::status
character(len=100)::dummy
double precision,allocatable, dimension(:,:) :: data_array1
double precision,allocatable, dimension(:,:) :: data_array2
character(len=100)::dimension
character(len=20) :: file_name1 = "value_10000_0.txt"
character(len=20) :: file_name2 = "value_10000_1.txt"
call count_line(file_name1,number_of_line1)
call count_line(file_name2,number_of_line2)
allocate(data_array1(number_of_line1,3),stat=status)
call read_data(file_name1,data_array1, number_of_line1,3)
allocate(data_array2(number_of_line2,3),stat=status)
if(status /=0) then
write(*,*) 'Error allocating 2.'
end if
call read_data(file_name2,data_array2,number_of_line2,3)
call find_intersection(data_array1,data_array2,number_of_line1,number_of_line2,3)
end program common_coord
Python vs Fortran
In entrambi i casi Python è utilizzato per task non numerici, traendo benefici
dalla semplicità nella gestione di:
• I/O
• interfacce
• gestione dell’applicazione
• reporting e post processing
• GUI
Strategie: C-API
Chiamare funzioni scritte in C/C++ e F77 in Python non è banale:
compilati interpretati
fortemente tipizzati VS debolmente tipizzati
La maniera nativa per scrivere un modulo Python in C consiste nell’usare le C-API di Python.
ESEMPIO:
Viene generata una libreria (extension module) che può essere importata in Python
con un import classico.
A questo livello in Python è IMPOSSIBILE distinguere tra una modulo pure python ed
una extension module.
Strumenti automatici:
• SWIG (Semplified Wrapper Interface Generator)
• F2PY
• Cython
• Ctypes
• …
F2PY
F2PY è un tool che permette di creare interfacce Python a funzioni scritte in Fortran e C.
F2PY è nativamente presente nella libreria Numpy e non necessità di installazione a parte se
Numpy è già presente.
ESEMPIO:
#!/usr/bin/env python
"“”hw: modulo in python""“
import math
In output abbiamo l’extension module sotto la forma di un hw.so (.dll in win32; .dylib
in Mac OS X)
F2PY
Possiamo testare che il modulo sia stato generato con successo :
>>>import hw
>>> hw.hw1(1,2)
0.14112000805986721
>>> hw.hw2(1,2)
Hello, World! sin( 3.000)=0.141120
Per moduli molto grandi è possibile rendere wrappate solo alcune funzioni, con la sintassi:
F2PY è stato inizialmente progettato per interfacciare funzioni fortran a Python ma può essere
utilizzato anche per creare wrapper di funzioni scritte in C.
F2PY
• Possiamo migliorare l’interfaccia prodotta e renderla più vicina allo ‘stile
Python’
$ f2py -h mult.pyf -m mult mult.f90
(mult.pyf)
python module mult python module mult
interface interface
subroutine fmult(a,b,c,n) subroutine fmult(a,b,c,n)
real*8 dimension(*) :: a real*8 dimension(n) :: a
real*8 dimension(*) :: b real*8 dimension(n) :: b
real*8 dimension(*) :: c real*8 intent(out), dimension
integer :: n (n) :: c
end subroutine fmult integer intent(hide), depend(
end interface a) ::
end python module mult n=len(a)
end subroutine fmult
Generato in automatico end interface
Python call: end python module mult
fmult(a,b,c,len(a))
Intervento manuale
#a,b Input
f2py -c mult.pyf mult.f90
#c Output
F2PY
>>> import numpy as np
>>> import mult
>>> a = np.array([1, 3, 4])
>>> b = np.array([2, 5, 1.5])
>>> c = mult.fmult(a, b)
>>> f = mult.fmult([3,4], [1.2,1.4])
>>> f
array([ 3.6, 5.6])
F2PY
Oppure inserendo le direttive come commento nei sorgenti
(mult2.f90)
subroutine fmult(a,b,c,n)
implicit none
integer, parameter :: dim=1000
real*8 :: a(n)
real*8 :: b(n)
real*8 :: c(n)
integer :: n, i
!f2py intent(hide), depend(a) :: n=len(a)
!f2py real*8 :: a(n)
!f2py real*8 :: b(n)
!f2py real*8, intent(out) :: c(n)
do i =1,n
c(i) = a(i) * b(i)
enddo
end
Swig
SWIG (Simplified Wrapper and Interface Generator) è un tool:
• E’ pensato per lavorare con codice C/C++ già esistente, usando solo una
interfaccia di scripting.
/* file: hw.h*/
#ifndef HW_H
#define HW_H
extern double hw1(double r1, double r2);
extern void hw2(double r1, double r2);
#endif
Esempio
/* file: hw.i */
%module hw
%{
/* include C header files necessary to compile the interface */
#include "hw.h"
%}
compile
Python Extension
Module
fib.so
Wrapping di codice scritto in C/C++
C/C++
Codice C generato da Cython
int fact(int n) {
static PyObject
if (n <= 1) *__pyx_pf_5cyfib_cyfib(PyObject
*__pyx_self, int __pyx_v_n) {
return 1; int __pyx_v_a; int __pyx_v_b;
PyObject *__pyx_r = NULL; PyObject
return n * fact(n-1); *__pyx_t_5 = NULL;
} const char *__pyx_filename = NULL;
...
for (__pyx_t_1=0;
__pyx_t_1<__pyx_t_2; __pyx_t_1+=1)
{
__pyx_v_i = __pyx_t_1;
__pyx_t_3 = (__pyx_v_a +
__pyx_v_b);
__pyx_t_4 = __pyx_v_a;
Cython __pyx_v_a = __pyx_t_3;
__pyx_v_b = __pyx_t_4;
cdef extern from “fact.h”: }
int _fact “fact”(int) ...
}
- Compilare i .pyx files con il Cython compiler, ottenendo dei .c file sorgenti
e compilare il codice C in maniera appropriata, per generare un
eseguibile, con i compilatori disponibili sulla propria piattaforma di lavoro.
//mylib.c
#include "mylib.h"
2u u u
k ( x , y )
k ( x , y )
t x
2
x y y
t
2
l 1
u l i , j ki 0.5, j (ui 1, j ui , j ) ki 0.5, j (ui , j ui 1, j )
x
2
t
ki , j 0.5 (ui , j 1 ui , j ) ki , j 0.5 (ui , j ui , j 1 )l 1
y
Fortran Function
…
print 'Start'
start=time.clock()
while t <= t_stop:
t += dt
up = mymod.calculate_u(dt, dx, dy, u, um, k)
um[:] = u
u[:] = up
print 'Stop'
stop=time.clock()
print 'Elapsed time ', stop-start, 's'
#Compute.pyx Cython
import numpy as np
cimport numpy as np
cimport cython
DTYPE=np.float
ctypedef np.float_t DTYPE_t
def calculate_u(float dt, float dx, float dy,np.ndarray[DTYPE_t, ndim=2, negative_indices=False] u,
np.ndarray[DTYPE_t, ndim=2, negative_indices=False] um,
np.ndarray[DTYPE_t, ndim=2, negative_indices=False] up,
np.ndarray[DTYPE_t, ndim=2, negative_indices=False] k):
cdef int m = u.shape[0]-1
cdef int n = u.shape[1]-1
cdef int i, j, start = 1
cdef float k_c, k_ip, k_im, k_jp, k_jm
cdef float hx = (dx/dt)**2
cdef float hy = (dy/dt)**2
for i in xrange(start, m):
for j in xrange(start, n):
k_c = k[i,j]
k_ip = 0.5*(k_c + k[i+1,j])
k_im = 0.5*(k_c + k[i-1,j])
k_jp = 0.5*(k_c + k[i,j+1])
k_jm = 0.5*(k_c + k[i,j-1])
up[i,j] = 2*u[i,j] - um[i,j]+hx*(k_ip*(u[i+1,j] - u[i,j]) -k_im*(u[i,j] - u[i-1,j])) +hy*(k_jp*(u[i,j+1] - u[i,j]) -k_jm*(u[i,j] - u[i,j-1]))
return up
Contronto