Linguaggio Python Speaker: Alessandro Giuliani Infelligent Agents and Soft-Computing Group Dept. of Electrical and Electronic Engineering University of Cagliari, Italy email: [email protected] Introduzione Introduzione Sviluppato da Guido Van Rossum (1991) Paradigmi: Object Oriented Programming Scripting (Perl, Tcl, …) (C++, Java, …) Python Functional Programming (CommonLisp, Haskell, …) Introduzione Popolarità Introduzione Popolarità Introduzione Popolarità Introduzione Chi Usa Python? NASA per lo sviluppo di sistemi di controllo; Yahoo! in alcuni servizi di internet; Google Youtube RedHat … Caratteristiche Generali Semplicità e facilità di lettura Esempio: stampare i valori interi da 0 a 9: Python: C++: for i in range(10): print i int i for (i=0; i<10; i++){ printf("%d", i);} Caratteristiche Generali Alcune statistiche dicono che un programma scritto in Python è tipicamente più corto e breve di 3-5 volte rispetto ad un programma scritto in Java ed addirittura di 5-10 volte rispetto ad un programma scritto in C++. Caratteristiche Generali Linguaggio non compilato! Python è in genere considerato un linguaggio interpretato, ma in realtà il codice sorgente non viene convertito direttamente in linguaggio macchina, ma passa prima da una fase di pre-compilazione in bytecode. Lo stesso bytecode viene quasi sempre riutilizzato dopo la prima esecuzione del programma, evitando così di dover ogni volta interpretare il sorgente ed incrementando di conseguenza le prestazioni. Caratteristiche Generali: Duck Typing “Quando io vedo un uccello che cammina come un'anatra, nuota come un'anatra e starnazza come un'anatra, io chiamo quell'uccello anatra” (J.W.Riley) Se una variabile la usiamo come numero intero, le associamo numeri interi, allora quella variabile denoterà un numero intero! Caratteristiche Generali: Duck Typing Linguaggio dinamicamente tipizzato! I tipi dati esistono e sono necessari ma non è necessario dichiararli esplicitamente. Variabili → puntatori ad oggetto (reference), sono gli oggetti ad essere dotati di tipo. Una variabile può cambiare la sua natura durante l'esecuzione del codice a = 10 … a = ['a', 'b', 'c'] implicitamente a è di tipo intero a diventa di tipo “lista” Caratteristiche Generali: Sintassi No terminatori di riga obbligatori Blocchi di codice specificati con indentazione Esempio: def fattoriale(x): if x == 0: return 1 return x * fattoriale(x-1) Caratteristiche Generali: Sintassi Caratteri principali : → istruzioni con blocchi indentati # → commenti (riga singola) ””” → commenti (su più righe) = → assegnazione == → test di uguaglianza ”””Questo è un commento su più righe””” def fattoriale(x): if x == 0: return 1 return x * fattoriale(x-1) #commento singolo Caratteristiche Generali: Moduli File che contengono definizioni e istruzioni Python. Il nome del file è il nome del modulo con il suffisso .py aggiunto. Il nome del modulo è disponibile (sotto forma di stringa) come valore della variabile globale __name__. I moduli possono importare altri moduli o parti di esso. import nomeModulo from nomeModulo import nomeFunzione Caratteristiche Generali: Tipi di dato Semplici int, long, float, bool, complex Sequenze Mutabili → consentite modifiche locali dell'oggetto liste, dizionari, set, file Immutabili → una volta create non si possono modificare stringhe, tuple Caratteristiche Generali: Tipi di dato Liste Serie ordinata di valori, ognuno identificato da un indice Gli elementi possono essere di tipo diverso Esempi: [10, 20, 30, 40] ["Pippo", "Pluto", "Paperino"] ["ciao", 2.0, 5, [10, 20]] Caratteristiche Generali: Tipi di dato Tuple Simili alle liste, l'unica differenza è che sono oggetti immutabili Esempi: (10, 20, 30, 40) ("Pippo", "Pluto", "Paperino") ("ciao", 2.0, 5, [10, 20]) Caratteristiche Generali: Tipi di dato Set Collezione non ordinata che non contiene elementi duplicati al suo interno. Esempio: a = [1, 2, 3, 3] set(a) → Output: {1, 2, 3} Caratteristiche Generali: Tipi di dato Dizionari Tipi di dato in cui si può usare qualsiasi tipo di dato immutabile come indice. Gli elementi appaiono in una sequenza separata da virgole. Ogni voce contiene un indice (chiave) univoco ed il corrispondente valore separati da due punti. Esempio: {"a" : 10, "b" : 20, "c" : 30) Strutture di Controllo e Iterazioni Controllo condizionale: if: … else: … if Condizione: #Se Condizione è vera esegui le istruzioni indentate … else: #altrimenti, se Condizione è falsa esegui le istruzioni indentate … Esempio: def fattoriale(x): if x == 0: return 1 else: return x * fattoriale(x-1) Strutture di Controllo e Iterazioni Cicli while Se è richiesta la ripetizione iterativa di un certo gruppo di istruzioni (tipo Ripeti-Finché) si adotta costrutto while: while (Condizione): #Finché Condizione è vera esegui le istruzioni indentate: … Esempio: def ContoAllaRovescia(n): while n > 0: print n n = n-1 print "Partenza!" Strutture di Controllo e Iterazioni Cicli for Equivalente al while, itera su strutture (es.liste e dizionari), e qualunque variabile indicizzata. L'iterazione è «definita», ovvero termina non appena gli elementi del dato sono stati esaminati tutti. for <iterazione su un dato iterabile>: #esegui le istruzioni indentate: … Esempio: #iterazione su una lista con for for x in lista: print x Funzione Range range → genera liste contenenti progressioni aritmetiche. Sintassi: range(n) → genera una sequenza di n numeri interi, partendo dal valore 0. range(10) → [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] range(start, stop) → genera una sequenza di numeri interi progressivi, partendo dal valore start, fino al valore stop (non incluso nella sequenza). range(1, 4) → [1, 2, 3] range(start, stop, step) → genera una sequenza di numeri interi progressivi, partendo dal valore start, fino al valore stop, non incluso nella sequenza, con passo pari a step. range(1, 8, 2) → [1, 3, 5, 7] Funzioni La sintassi per definire una funzione è molto semplice: def nome_funzione(<lista parametri separati da virgola>): <blocco istruzioni> return <risultato> def fattoriale(x): if x == 0: return 1 return x * fattoriale(x-1) Funzioni: Scope Variabili locali → utilizzabili solo dalle funzioni. Variabili globali → appartenenti al namespace del modulo (utilizzabili al di fuori della funzione). Meccanismo di ricerca del nome della variabile VARIABILE VARIABILE NAMESPACE NAMESPACE LOCALE LOCALE NAMESPACE NAMESPACE GLOBALE GLOBALE FUNZIONI FUNZIONI BUILT-IN BUILT-IN Questo meccanismo permette di utilizzare il valore delle variabili globali, ma di non poterle mai modificare, in quanto un nuovo assegnamento alla variabile provoca la creazione dello stesso nome in un namespace nuovo. Funzioni: Scope Esempio: def func(): a = 20 a = 10 func() print a Output: 10 Funzioni: Passaggio di Parametri Il comportamento è paragonabile al passaggio per riferimento Variabili → etichette applicate agli oggetti Esempio def func(x,y): x.append(30) y += 1 a = [10, 20] b = 1 func(a,b) print a print b Funzioni: Passaggio di Parametri Output [10, 20, 30] → la variabile a è stata modificata 1 → la variabile b non è stata modificata! Perché diversi comportamenti? La variabile a è una lista → mutabile! La variabile b è un intero → immutabile! Funzioni: Parametri Opzionali Parametri che assumono un valore prestabilito se non vengono valorizzati Esempio def func(a, b = 0): print(a,b) x = 1 y = 2 print func(x, y) → Output: 1 2 print func(x) → Output: 1 0 Funzioni con Numero di Parametri Variabile Numero variabile di argomenti → utilizzo degli asterischi *… → lista di parametri **… → dizionario di parametri Esempio def func(*args,**kwargs): print 'lista di parametri:', args print 'dizionario di parametri:', kwargs func(1, 2, 3 , b = 4, c = 5) Output: lista di parametri: (1, 2, 3) dizionario di parametri: {'c': 5, 'b': 4} Funzioni Lambda Funzioni inline anonime, identificate dalla keyword lambda Sintassi: lambda <argomenti> : <espressione> Equivalente ad un funzione con argomenti argomenti e con valore di ritorno espressione. g = lambda x: x**2 print 'g(2):', g(2) print 'g:(4)', g(4) Output: g(2): 4 g(4): 16 List Comprehension Modalità di estrazione di sottoinsiemi da liste (o dizionari). Permette di agire sugli elementi dell’insieme e filtrarli allo stesso tempo. Operazioni iterative più immediate, flessibili ed efficienti rispetto alle consuete istruzioni cicliche Sintassi lista = [espressione for variabile in altra_lista <if altra_espressione>] List Comprehension Esempio: data una lista a, creare una lista contenente i quadrati degli elementi di a a = [1, 2, 3, 4] b = [x**2 for x in a] print b Output → [1, 4, 9, 16] Esempio 2: data una lista a, creare una lista contenentegli elementi di a che siano maggiori o uguali a 2 a = [1, 4, 2, 0, 3] b = [x for x in a if x >= 2] print b Output → [4, 2, 3] Gestione delle Eccezioni Eccezione: errore rilevati durante l'esecuzione. Senza nessun accorgimento: interruzione dell'esecuzione a, b = 5, 0 print a / b Output: traceback (most recent call last): File “<pyshell#5>”, line 1, in ? print a / b ZeroDivisionError: integer division or modulo by zero Gestione delle Eccezioni Gestire le eccezioni - sintassi: try: <gruppo di istruzioni sotto test> except <nome della classe di errore>: <gruppo di istruzioni da eseguire in caso di errore> else: #opzionale <gruppo di istruzioni2> Gestione delle Eccezioni Esempio: a, b = 5, 0 try: print a / b except ZeroDivisionError: print ‘Errore: divisione per zero!' Output: ‘Errore: divisione per zero!' Iteratori Iteratore: oggetto che consente di visitare tutti gli elementi contenuti in un altro oggetto. Il ciclo for usa implicitamente un iteratore. Maniera esplicita: iter() → crea un iteratore. next() → rende l'elemento successivo Esempio: it = iter(sequence) try: while True: print it.next() except StopIteration: pass Generatori Strumenti per creare iteratori. Sono scritti come funzioni regolari, ma usano l'istruzione yield ogni qualvolta restituiscano dei dati. Esempio: def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] for char in reverse('golf'): print char Output: f l o g Decoratori Decoratore: funzione che modifica un'altra funzione. Python passa la funzione da decorare al decoratore, e la sostituisce con il risultato. Esempio: def myDecorator(function): print 'I am decorating!' return function def hello(): print 'hello world!' hello = myDecorator(hello) hello() Output: I am decorating! hello world! Decoratori Python fornisce una sintassi specifica, che rende più leggibile il codice. Esempio: def myDecorator(function): print 'I am decorating!' return function @myDecorator def hello(): print 'hello world!' hello() Output: I am decorating! hello world! Programmazione Orientata agli Oggetti Classi in Python Sintassi: class <nome classe> [(<classe madre>,…)]: <elenco dati membro da inizializzare> <elenco metodi> Dati membro → espressi come normali variabili, inizializzate mediante semplice assegnamento o definiti al momento dell’utilizzo. Metodi → stessa sintassi delle funzioni, con alcuni accorgimenti: devono avere come primo parametro l’oggetto stesso → parametro self. Esempio: class myClass: i = 10 def func(self): return 'Hello world' Classi in Python Sintassi: class <nome classe> [(<classe madre>,…)]: <elenco dati membro da inizializzare> <elenco metodi> Dati membro → espressi come normali variabili, inizializzate mediante semplice assegnamento o definiti al momento dell’utilizzo. Metodi → stessa sintassi delle funzioni, con alcuni accorgimenti: devono avere come primo parametro l’oggetto stesso → parametro self. Esempio: Nome classe class myClass: Dato membro i = 10 def func(self): Metodo return 'Hello world' Classi in Python Istanza di un oggetto: a = myClass() a è un oggetto della classe myClass, che contiene l'attributo i e il metodo func print a.i → Output: 10 a.f() → Output: Hello world Classi in Python: Creazione e Inizializzazione A differenza di altri linguaggi, gli oggetti sono costruiti e inizializzati in due passi successivi separati: __new__ → restituisce istanza non inizializzata __init__ → inizializza l'istanza Sono richiamate automaticamente in fase di creazione di un'istanza: a = MyClass(…) equivale a: a = MyClass.__new__(…) a.__init__(…) Se non trovate, implicitamente vengono richiamate dalla classe object (da cui derivano implicitamente tutti gli oggetti del linguaggio) Classi in Python: Creazione e Inizializzazione Inizializzazione: metodo __init__ Esempio: class myClass: def __init__(self, x): self.i = x a = myClass(10) print a.i → Output: 10 Classi in Python: Metodi N.B. Convenzionalmente, il primo argomento dei metodi è chiamato self. Questa non è niente di più che una convenzione: il nome non ha assolutamente alcun significato speciale in Python. class myClass: def __init__(pincopallino, x): pincopallino.i = x a = myClass(10) print a.i → Output: 10 Classi in Python: Attributi In molti linguaggi gli oggetti hanno un numero e un tipo di attributi predeterminati dalla classe. In Python oggetti della stessa classe possono avere attributi differenti __init__ non vincola il numero di attributi di un oggetto. class myClass: def __init__(self, x): self.i = x a = myClass(10) a.y = 5 print a.y → Output: 5 Classi in Python: Oggetti Funzione Qualsiasi oggetto funzione che sia attributo di una classe definisce un metodo per le istanze di tale classe. Non è necessario la definizione di funzione sia racchiusa nella classe def f(self): return 'Hello world' class myClass: func = f def g(self, x): print x h = g a = myClass() a.func() → Output: 'Hello world' a.h(2) → Output: 2 Classi in Python: Variabili Private Sintassi: come minimo due trattini bassi all'inizio, al più un trattino basso in coda: class myClass: def __init__(self, a): self.__x = a Al di fuori della classe non si può accedere all'attributo privato: a = myClass(10) a.__x → Output: AttributeError: myClass instance has no attribute '__x' Classi in Python: Variabili Private In realtà nulla in Python è realmente privato!!! I nomi dei metodi e degli attributi privati vengono cambiati a livello di codice eseguito: __attributoPrivato → _NomeClasse__attributoPrivato Esempio: class myClass: def __init__(self, a): self.__x = a a = myClass(10) a._myClass__x → Output: 10 Gli attributi privati essenzialmente permettno alle sottoclassi di usare attributi con lo stesso nome senza modificare il comportamento di eventuali metodi che ne facevano uso Classi in Python: Property Consentono di costruire un “attributo virtuale” che richiama delle funzioni (in lettura, scrittura, cancellazione). Si definiscono richiamando la funzione built-in property: x = property(fget=None, fset=None fdel=None) fget → richiama la funzione di lettura dell'attributo fget → richiama la funzione di scrittura dell'attributo fdel → richiama la funzione di cancellazione dell'attributo Se non specificate non è possibile effettuare l'operazione associata. Classi in Python: Property Esempio: class myClass: def __init__(self, x): self.__x = x def getX(self): return self.__x def setX(self,value): self.__x=value x = property(fget = getX, fset=setX) a = myClass(10) a.x = 20 #richiama setX print a.x #richiama getX Classi in Python: Property Esempio: class myClass: def __init__(self, x): self.__x = x def setX(self,value): self.__x=value x = property(fset=setX) a = myClass(10) a.x = 20 #richiama setX print a.x #restituisce unreadable attribute' un errore: 'AttributeError: Classi in Python: Overloading degli Operatori Gli operatori algebrici possono essere ridefiniti, facendoli corrispondere a funzioni speciali della classe In questo modo e' possibile definire operazioni fra oggetti complessi con la sintassi delle normali operazioni algebriche. Questo viene fatto definendo le funzioni speciali; queste sono le funzioni vengono chiamate da Python quando incontra operazioni fra istanze della classe. Esempio di funzioni speciali __add__(a, b) # a + b __sub__(a, b) # a - b __mul__(a, b) # a * b __div__(a, b) # a / b … Classi in Python: Overloading degli Operatori Esempio di overloading: addizione class Point: def __init__(self, x, y): self.x = x self.y = y def __add__(self, point): self.x += point.x self.y += point.y a = Point(1,2) b = Point(3,4) a + b print a.x, a.y → Output: 4 6 Classi in Python: Metodi Statici Si comportano come funzioni globali dentro il namespace della classe. Simili ai metodi statici di Java e C++ Sintassi: o tramite metodo staticmethod o tramite decoratore @staticmethod. In entrambi i casi non si devono passare parametri impliciti (self) Esempio: data la classe class P(): … def f(): print 'Hello world' Classi in Python: Metodi Statici Rendere f() statico tramite metodo staticmethod: class P(): … def f(): print 'Hello world' f = staticmethod(f) … Tramite decoratore: class P(): … @staticmethod def f(): print 'Hello world' f = staticmethod(f) … Classi in Python: Metodi Statici In entrambi i casi, i metodi statici possono essere chiamati sia dalla classe che da un'istanza della classe a = P() a.f() → 'Hello world' P.f() → 'Hello world' Classi in Python: Ereditarietà Sintassi: class NomeClasseDerivata(NomeClasseBase): <istruzione-1> … <istruzione-N> Al posto di NomeClasseBase è permessa anche un'espressione, utile quando la classe base è definita in un altro modulo: class NomeClasseDerivata(nomemodulo.NomeClasseBase) Se un attributo non viene rinvenuto nella classe, viene cercato nella classe base. Tale regola viene applicata ricorsivamente se la classe base è a sua volta derivata da una qualche altra classe Classi in Python: Ereditarietà Esempio: class A: def __init__(self): self.x = 1 class B(A): def __init__(self): A.__init__(self) self.x = 2 b = B() print b.x, b.y → Output: 1 2 A A BB Classi in Python: Ereditarietà Multipla Definizione di classe con classi base multiple: class NomeClasseDerivata(Base1, Base2, … ): <istruzione-1> … <istruzione-N> Esempio: class C(A,B): … BB A A CC Classi in Python: Ereditarietà Multipla Regola di risoluzione usata per i riferimenti agli attributi di classe: Prima-in-profondità Poi da-sinistra-a-destra. A A CC BB D D D→B→A→C Classi in Python: Classe object object è la classe di base da cui ereditano tutti i tipi built-in (list, dict, str...) e tutte le classi definite dal programmatore, in maniera implicita, esplicita, o indiretta (es. ereditando da tipi built-in). class MyClass(): … equivale a: class MyClass(object): … Classi in Python: Polimorfismo Funzione polimorfica → assume una forma diversa in base al tipo di oggetto sul quale viene applicato. Esempio: class Gatto(): def verso(self): return 'Miao' class Cane(): def verso(self): return 'Bau' a = Gatto() b = Gatto() a.verso() → Output: 'Miao' b.verso() → Output: 'Bau' Metaclassi (cenni) Metaclasse → classe le cui istanze sono a loro volta classi. Internamente Python crea le classi istanziando la metaclasse type E' possibile estendere la metaclasse type per creare una propria metaclasse, ridefinendo i metodi __init__ e __new__ Per utilizzare la propria metaclasse invece della metaclesse type si usa una sintassi del tipo: class nomeclassse(metaclass = nomemetaclasse): Python3 Tutte le slide precedenti sono relative alle versioni Python 2.XX Python 3.0 è stato rilasciato nel 2008. L’obiettivo è stato quello di ripulire il codice base e rimuovere la ridondanza, mettendo in chiaro che c’è un solo modo per eseguire un determinato compito. Successivamente al rilascio del Python 3.0 nel 2008 , Python 2.7 è stato pubblicato il 3 luglio 2010 e previsto come l’ultimo dei rilasci 2.x. Python3: Differenze con Python 2 print → non più una istruzione ma una funzione print 'Hello world' → print('Hello World') Divisione fra interi. In Python2 ritorna un intero troncando il risultato, in Python3 restituisce un float (anche se il risultato è un intero) range → restituisce non più una lista file eliminata … Python2.7: Utilizzo di Funzioni Python 3 E' possibile importare funzionalità di Python3 col modulo __future__ Ad esempio, per importare la funzionalità di divisione tra interi di Python3: from __future__ import division … a = 5/2 print a → 2.5 N.B. In Python 2 l'output sarebbe stato: 2 Python2 o Python3? Python 3 continuerà ad essere sostenuto e sviluppato, mentre Python 2.7 no (non più supportato dal 2020). Python 2.7 è vista come release intermedia tra le versioni precedenti di Python 2 e Python 3.0, e continua ad essere una scelta molto popolare per i programmatori (e soprattutto dalle aziende) grazie alla sua compatibilità con molte solide librerie. Applicazioni Sviluppo Web framework leggeri → Bottle, Bottle Webpy, Webpy Flask … framework di sviluppo web → Django, Django TurboGears … web application → Zope e il suo CMS Plone framework Twisted → per scrivere servizi di rete CGI (Common Gateway Interface) scripts creazione di socket... Applicazioni Accesso ai database: modalità di accesso → DB-API. Supporta nativamente diversi database (relazionali o nonrelazionali), oltre ad essere disponibili attraverso ODBC. Oracle MySQL PostgreSQL SQL Server SQLite Applicazioni Applicazioni desktop e grafiche libreria di sviluppo TkInter wxPython (fusione della libreria C++ wxWidgets con Python) PyQt PyGTK GenroPy → framework applicativi web che si presentano come applicativi desktop Applicazioni Giochi e grafica 3D: Python è ampiamente usato per lo sviluppo di giochi sia a livello commerciale che "hobbistico". PyGame PyKyra Motori di Rendering 3D Applicazioni Calcolo scientifico e numerico: Python è ampiamente usato in ambiente scientifico MatPlotLib → tool per grafici 2D e 3D NumPY → libreria per analisi statistiche e matriciali SK-Learn → funzioni di calcolo scientifico e intelligenza artificiale Conclusione: Usare Python o no? Vantaggi principali Qualità Produttività di sviluppo Portabilità Svantaggio principale Linguaggio non compilato The End!!!