Seminario IL Implentazione degli oggetti in Python Antonio Cuni Marco Tozzi.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Introduzione al linguaggio C++
Recupero debito quarto anno Primo incontro
Introduzione alla programmazione A. Ferrari. Il linguaggio C Nel 1972 Dennis Ritchie nei Bell Laboratories progettò il linguaggio C Il linguaggio possiede.
PHP.
MATLAB. Scopo della lezione Programmare in Matlab Funzioni Cicli Operatori relazionali Esercizi vari.
Type Checking (1° parte)
Algoritmi e Programmazione
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
1 Informatica Generale Susanna Pelagatti Ricevimento: Mercoledì ore presso Dipartimento di Informatica, Via Buonarroti,
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Caratteri e stringhe di caratteri
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Funzioni definite dall’utente
Informatica 2. Concetti fondamentali di programmazione Programmare vuol dire scrivere un algoritmo in un linguaggio che faccia funzionare un calcolatore.
1 Programmazione ad oggetti in Java E.Mumolo, DEEI
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
Corso di Laurea in Biotecnologie Informatica (Programmazione)
Corso di Informatica (Programmazione)
1 Corso di Informatica (Programmazione) Lezione 13 (21 novembre 2008) Programmazione in Java: stringhe e array.
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab m-file m-file script script Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali.
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali Esercizi vari Esercizi.
Introduzione al linguaggio Java
Introduzione agli stream e alle classi
Perché.Net e non più COM/DCOM ? Superamento dei problemi di COM: Richiede una infrastruttura "non semplice" da ogni applicazione (ad esempio Class Factory.
Lezione 4: Costrutti Condizionali Prof. Raffaele Montella.
La Riflessione computazione Elisa Ferrando. Cos è la Riflessione La Riflessione Sistema riflessivo Sistema computazionale.
Lezione 2 Programmare in ASP
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
Corso di PHP.
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
Javascript: fondamenti, concetti, modello a oggetti
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
BIOINFO3 - Lezione 201 Come in ogni corso di introduzione ad un linguaggio di programmazione, proviamo a scrivere lormai celebre primo programma di prova.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
File e Funzioni Si possono distinguere tre tipi di file che vengono utilizzati in MATLAB: M-file: hanno estensione .m e in essi vengono memorizzati i.
CORSO DI PROGRAMMAZIONE II Lezione 22
Programmazione ad oggetti
Introduzione a Javascript
Variabili Numeriche –Interi (byte, short, int, long): complemento a 2 –A virgola mobile (float, double): IEEE 745 Alfanumeriche –Carattere (char): Unicode.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
Parte 3 Lo stato: variabili, espressioni ed assegnazioni
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 7 Tipi di dato e strutture dati Specifica e realizzazione di strutture informative come classi.
1 Tipi di Dato §descrittori, tipi, controllo e inferenza dei tipi §specifica (semantica) e implementazione di tipi di dato l implementazioni “sequenziali”
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
TW Asp - Active Server Pages Nicola Gessa. TW Nicola Gessa Introduzione n Con l’acronimo ASP (Active Server Pages) si identifica NON un linguaggio di.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Sommario Oggetti immutabili e non Tipi Primitivi: String, Arrays.
1 Macchine astratte, linguaggi, interpretazione, compilazione.
Esercitazione del 9 marzo 2007 Ereditarieta’. Richiami Definire sottoclassi (ereditarieta’) Overriding Specificatori di accesso (private, protected) Principio.
Cloud informatica V anno. Introduzione a PHP Lo scripting PHP PHP è un linguaggio di scripting lato server. Le caratteristiche di un linguaggio di scripting.
Eprogram informatica V anno. Introduzione a PHP Introduzione La diffusione di PHP ha avuto un notevole incremento dalla fine degli anni Novanta a oggi,
Fondamenti di informatica T-A Esercitazione 3 : Classi, metodi, visibilità, metodi statici AA 2012/2013 Tutor : Domenico Di Carlo.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Il C `e un linguaggio di programmazione di uso generale, originariamente sviluppato per la scrittura del sistema operativo Unix, ed oggi disponibile su.
“ Pseudocodice ” Un programma per computer lavorerà su in insieme di “ variabili ” contenenti i dati del problema, soluzioni intermedie, soluzioni finali.
Python Giovanni Aglialoro slide tratte anche dalle presentazioni di Marco Barisione, Antonio Cuni, Marco Tozzi. Guido van Rossum I Monty Python
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
Introduzione alle Classi e agli Oggetti in Java 1.
Programmazione ad Oggetti in Python
Python Guido van Rossum I Monty Python Giovanni Aglialoro
Transcript della presentazione:

Seminario IL Implentazione degli oggetti in Python Antonio Cuni Marco Tozzi

Seminario IL Sommario 1.Panoramica sui linguaggi di scripting 2.Panoramica su Python 3.Implementazione degli oggetti in Python

Seminario IL 1. Panoramica sui linguaggi di scripting

Seminario IL Linguaggi di scripting Che cos’è uno script?Che cos’è uno script? Un piccolo programma per automatizzare unUn piccolo programma per automatizzare un lavoro ripetitivo e noioso Una serie di comandi inviati ad un “ambiente esterno” che li interpreta e esegueUna serie di comandi inviati ad un “ambiente esterno” che li interpreta e esegue Ambiente Esterno:Ambiente Esterno: SO tramite shellSO tramite shell Programma applicativo es: MS OfficeProgramma applicativo es: MS Office Con l’aumento della complessità la distinzione tra script e programmi è sempre più sfumata

Seminario IL Linguaggi di scripting (2) Che cos’è un linguaggio di scripting?Che cos’è un linguaggio di scripting? Supporto per scrivere velocemente eSupporto per scrivere velocemente e facilmente script Programmazione ad alto livello, consente di tralasciare dettagli di basso livelloProgrammazione ad alto livello, consente di tralasciare dettagli di basso livello (es: gestione della memoria) Alcuni sono talmente potenti da consentire lo sviluppo di intere applicazioniAlcuni sono talmente potenti da consentire lo sviluppo di intere applicazioni

Seminario IL Linguaggi di scripting: esempi Specializzati in compiti specifici:Specializzati in compiti specifici: awk elaborazione di testo organizzato in righe e colonneawk elaborazione di testo organizzato in righe e colonne sed elaborazione di testo arbitrariosed elaborazione di testo arbitrario Che consentono di controllare un’applicazione ospitante:Che consentono di controllare un’applicazione ospitante: Visual Basic for Applications (MS Office)Visual Basic for Applications (MS Office) Javascript (web browser)Javascript (web browser) Emacs Lisp (Emacs)Emacs Lisp (Emacs) General purpouse adatti per applicazioni più complesse:General purpouse adatti per applicazioni più complesse: PythonPython PerlPerl RubyRuby

Seminario IL Linguaggi interpretati Non richiedono alcuna compilazione esplicitaNon richiedono alcuna compilazione esplicita In realtà in molti casi (Python, Perl, Emacs Lisp) c’è un compilatore che produce byte- code interpretato da una VMIn realtà in molti casi (Python, Perl, Emacs Lisp) c’è un compilatore che produce byte- code interpretato da una VM Nota: stessa architettura usata da Java e.NET solo che in questi è il programmatore a chiedere la compilazione

Seminario IL Tipizzazione forte VS debole Abbiamo spesso (non sempre!) che: Linguaggi di script tipizzazione deboleLinguaggi di script tipizzazione debole Es: sommiamo un numero ad una stringa JavascriptJavascript 3+"3" == "33"3+"3" == "33" 3-"3" == 03-"3" == 0 PHPPHP 3+"3" == 63+"3" == 6 3+"ciao" == 33+"ciao" == 3

Seminario IL Debole: comoda per script semplici e breviDebole: comoda per script semplici e brevi A lungo andare può portare a bug molto insidiosi e difficili da trovareA lungo andare può portare a bug molto insidiosi e difficili da trovare Es di linguaggio con tipizzazione forte: Python avrebbe generato un errore negli esempi precedentiEs di linguaggio con tipizzazione forte: Python avrebbe generato un errore negli esempi precedenti Tipizzazione forte VS debole (2)

Seminario IL Tipizzazione statica VS dinamica Tipizzazione statica:Tipizzazione statica: eseguibili più efficientieseguibili più efficienti intercettare alcuni (pochi!) errori a compile- timeintercettare alcuni (pochi!) errori a compile- time In quasi tutti i linguaggi di scripting abbiamo tipizzazione dinamica:In quasi tutti i linguaggi di scripting abbiamo tipizzazione dinamica: Tipo determinato a run-time e può variare durante l’esecuzioneTipo determinato a run-time e può variare durante l’esecuzione Notevole flessibilitàNotevole flessibilità

Seminario IL 2. Introduzione a Python

Seminario IL Python: introduzione È un linguaggio di programmazione:È un linguaggio di programmazione: InterpretatoInterpretato Di altissimo livelloDi altissimo livello Semplice da imparare e usareSemplice da imparare e usare Potente e produttivoPotente e produttivo Ottimo anche come primo linguaggio (molto simile allo pseudocodice)Ottimo anche come primo linguaggio (molto simile allo pseudocodice) InoltreInoltre È open source ( open source ( È multipiattaformaÈ multipiattaforma È facilmente integrabile con C/C++ e JavaÈ facilmente integrabile con C/C++ e Java

Seminario IL Python: introduzione (2) È veramente usato da qualcuno? RedHatRedHat anaconda (installazione), tool di configurazione grafici, log viewer NASANASA Industrial Light and MagicIndustrial Light and Magic quelli che fanno gli effetti speciali per Star Wars... E molti altri …E molti altri …

Seminario IL Python: l’interprete interattivo Python dispone di un interprete interattivo molto comodo e potente: Avvio: digitare python al prompt di una shellAvvio: digitare python al prompt di una shell appare ora il prompt >>> pronto a ricevere comandi Possiamo ora inserire qualsiasi costrutto del linguaggio e vedere immediatamente l’output:Possiamo ora inserire qualsiasi costrutto del linguaggio e vedere immediatamente l’output: >>> >>> print "Hello world!" Hello world! L’ istruzione print stampa a video il risultato di un’espressione

Seminario IL Python come calcolatrice Possiamo usare l’interprete interattivo come calcolatrice:Possiamo usare l’interprete interattivo come calcolatrice: >>> (6+3) / 2 4 >>> 3/2 1 >>> 3/ Per usare una variabile basta assegnarle un valore; c’e‘ anche l’operatore ** che rappresenta l’elevamento a potenza:Per usare una variabile basta assegnarle un valore; c’e‘ anche l’operatore ** che rappresenta l’elevamento a potenza: >>> x = 3+5 >>> x 8 >>> x**2 64

Seminario IL Python: manipolazione di stringhe Per indicare una stringa bisogna racchiuderla tra virgolette a differenza di molti altri linguaggi, possiamo usare sia le virgolette singole che quelle doppiePer indicare una stringa bisogna racchiuderla tra virgolette a differenza di molti altri linguaggi, possiamo usare sia le virgolette singole che quelle doppie >>> print "ciao" ciao >>> print ’Ho detto "ciao"’ Ho detto "ciao" >>> print "ecco l’apice" ecco l’apice Possiamo creare delle stringhe multilinea usando le triple virgolette (sia ’’’ che """):Possiamo creare delle stringhe multilinea usando le triple virgolette (sia ’’’ che """): >>> frase = """questa e‘ una... stringa che occupa... tre righe""" >>> print frase questa e‘ una stringa che occupa tre righe

Seminario IL Python: stringhe (2) Possiamo concatenare due stringhe usando l’operatore +:Possiamo concatenare due stringhe usando l’operatore +: >>> print ’ciao ’ + ’ciao’ ciao ciao Possiamo ripetere una stringa usando l’operatore *:Possiamo ripetere una stringa usando l’operatore *: >>> print ’-’ * >>> print ’ciao ’ * 3 ciao ciao ciao Per accedere ai singoli caratteri di una stringa, usiamo l’operatore []; l’indice puo‘ anche essere negativo:Per accedere ai singoli caratteri di una stringa, usiamo l’operatore []; l’indice puo‘ anche essere negativo: >>> ’ciao’[0] ’c’ >>> ’ciao’[1] ’i’ >>> ’ciao’[-1] ’o’

Seminario IL Python: stringhe(3) Le stringhe in Python, come in Java, sono immutabili: non e‘ possibile assegnare un nuovo valore ai singoliLe stringhe in Python, come in Java, sono immutabili: non e‘ possibile assegnare un nuovo valore ai singolicaratteri. Sottostringhe e slices:Sottostringhe e slices: usiamo una variante dell’operatore [] chiamata slice notation: >>> ’una stringa’[0:3] ’una’ >>> ’una stringa’[1:-1] ’na string’

Seminario IL Python: slices mystring[i:j] restituisce tutti i caratteri compresi tra gli indici i (compreso) e j (escluso): Se il primo indice viene omesso, la slice parte dal primo carattere della stringa:Se il primo indice viene omesso, la slice parte dal primo carattere della stringa: >>> ’una stringa’[:3] ’una’ Se il secondo indice viene omesso, la slice arriva sino all’ulitmo carattere della stringa:Se il secondo indice viene omesso, la slice arriva sino all’ulitmo carattere della stringa: >>> ’una stringa’[4:] ’stringa’

Seminario IL Python: metodi delle stringhe Le stringhe sono oggetti a tutti gli effetti. Alcuni esempi:Le stringhe sono oggetti a tutti gli effetti. Alcuni esempi: >>> ’Ciao’.upper() ’CIAO’ >>> ’Ciao’.lower() ’ciao’ >>> ’ciao anto’.replace(’anto’, ’marco’) ’ciao marco’ Per ottenere la lunghezza c’è la funzione len():Per ottenere la lunghezza c’è la funzione len(): >>> len(’ciao’) 4 Attenzione! len() è una funzione, si applica anche ad altre sequenze

Seminario IL Python: liste Una lista e‘ un oggetto composto simile per molti versi agli array presenti in altri linguaggi.Una lista e‘ un oggetto composto simile per molti versi agli array presenti in altri linguaggi. Possiamo creare una lista racchiudendone gli elementi tra parentesi quadre e separandoli con una virgola (gli elementi possono anche avere tipi diversi):Possiamo creare una lista racchiudendone gli elementi tra parentesi quadre e separandoli con una virgola (gli elementi possono anche avere tipi diversi): >>> mylist = [0, 100, ’ciao’, 15.4] >>> mylist [0, 100, ’ciao’, 15.4] Per accedere agli elementi di una lista usiamo la stessa notazione usata per le stringhe:Per accedere agli elementi di una lista usiamo la stessa notazione usata per le stringhe: >>> mylist[1] 100 >>> mylist[:2] [0, 100]

Seminario IL Python: liste (2) Le liste sono oggetti mutabili: possiamo modificarne la composizioneLe liste sono oggetti mutabili: possiamo modificarne la composizione >>> mylist[1] = ’salve’ >>> mylist [0, ’salve’, ’ciao’, 15.4] Come per le stringhe, anche le liste hanno dei metodi:Come per le stringhe, anche le liste hanno dei metodi: >>> mylist [0, ’salve’, ’ciao’, 15.4] >>> mylist.append(1) >>> mylist [0, ’salve’, ’ciao’, 15.4, 1]

Seminario IL Python: liste (3) Per aggiungere un elemento in una posizionePer aggiungere un elemento in una posizione qualunque, usiamo il metodo insert(): >>> mylist.insert(1, 100) >>> mylist [0, 100, ’salve’, ’ciao’, 15.4, 1] Possiamo ordinare una lista usando il metodo sort(), ed invertirla con il metodo reverse():Possiamo ordinare una lista usando il metodo sort(), ed invertirla con il metodo reverse(): >>> mylist = [1, 5, 7, 4, 10] >>> mylist.sort() >>> mylist [1, 4, 5, 7, 10] >>> mylist.reverse() >>> mylist [10, 7, 5, 4, 1]

Seminario IL Python: Tuple Un altro tipo di sequenza questa volta immutabile In genere sono racchiuse tra parentesi tonde:In genere sono racchiuse tra parentesi tonde: >>> mytuple = (1, ’ciao’, 100) >>> mytuple (1, ’ciao’, 100) Possiamo usare una tupla quando in altri linguaggi siamo costretti a ricorrere a costrutti più complessi (es: struct del C) es:Possiamo usare una tupla quando in altri linguaggi siamo costretti a ricorrere a costrutti più complessi (es: struct del C) es: >>> mypoint = (4, 6) possiamo assegnare in un sol colpo ogni elemento ad una variabile diversa:possiamo assegnare in un sol colpo ogni elemento ad una variabile diversa: >>> mypoint (4, 6) >>> x, y = mypoint >>> x 4 >>> y 6

Seminario IL Python: dizionari Python offre anche un supporto nativo per le hash table, chiamate dizionari. espresso come sequenza di coppie chiave:valore racchiuse tra parentesi graffe e separate da virgole:espresso come sequenza di coppie chiave:valore racchiuse tra parentesi graffe e separate da virgole: >>> voti = {’programmazione’: 18, ’LP’: 26, ’Implementazione’: 30} >>> voti {’programmazione’: 18, ’Implementazione’: 30, ’LP’: 26} per accedere ai singoli elementi:per accedere ai singoli elementi: >>> voti[’LP’] 26 >>> voti[’Info Gen’] = 20 >>> voti {’programmazione’: 18, ’Implementazione’: 30, ’Info Gen’: 20, ’LP’: 26}

Seminario IL Python: esempio di algoritmo Calcoliamo i numeri di Fibonacci:Calcoliamo i numeri di Fibonacci: >>> # Serie di Fibonacci:... # Ogni numero e‘ la somma... # dei due numeri precedenti... a, b = 0, 1 >>> while b >> while b < 10:... print b... a, b = b, a+b

Seminario IL Osservazioni per delimitare il ciclo non usiamo né {} né begin/end: il blocco e‘ delimitato solo ed esclusivamente dall’ indentazione.per delimitare il ciclo non usiamo né {} né begin/end: il blocco e‘ delimitato solo ed esclusivamente dall’ indentazione. assegnamento multiploassegnamento multiplo per delimitare le istruzioni non serve il ;per delimitare le istruzioni non serve il ; sembrerebbe che Python non abbia tipi in realtà è strongly typed:sembrerebbe che Python non abbia tipi in realtà è strongly typed: Ogni oggetto ha un tipo che non può cambiare maiOgni oggetto ha un tipo che non può cambiare mai Le variabili (references) sono come delle “etichette” che si “appiccicano” agli oggettiLe variabili (references) sono come delle “etichette” che si “appiccicano” agli oggetti

Seminario IL Python Funzioni La keyword def introduce una definizione di funzione …La keyword def introduce una definizione di funzione … Proviamo a scrivere una funzione che calcoli i numeri di fibonacci:Proviamo a scrivere una funzione che calcoli i numeri di fibonacci: >>>def fib(n):... “””Stampa la serie di Fibonacci fino a n”””... a, b = 0, 1... while b < n:... print b,... a, b = b, a+b... >>> fib(2000) Il primo statement può essere una docstring usata da tools che producono documentazioneIl primo statement può essere una docstring usata da tools che producono documentazione

Seminario IL Python funzioni (2) Gli argomenti sono passati tramite call by value (value è un object reference quindi call by object reference)Gli argomenti sono passati tramite call by value (value è un object reference quindi call by object reference) L’esecuzione di una funzione introduce una nuova symbol table per le variabili locali (look up: local,global,built-in table)L’esecuzione di una funzione introduce una nuova symbol table per le variabili locali (look up: local,global,built-in table) Function name è introdotto nella symbol table correnteFunction name è introdotto nella symbol table corrente Il nome ha un tipo riconosciuto come user-defined function e un valoreIl nome ha un tipo riconosciuto come user-defined function e un valore Può essere assegnato ad un altro nome (es: rinomina)Può essere assegnato ad un altro nome (es: rinomina) >>> fib >>> f = fib >>> f(100)

Seminario IL Python funzioni (3) Si possono specificare argomenti di default, quindi le chiamate possono anche non specificarli tutti:Si possono specificare argomenti di default, quindi le chiamate possono anche non specificarli tutti: >>> def info(cognome, nome='Marco'):... print cognome, nome... >>> info('Tozzi') Tozzi Marco Possono essere invocate usando gli argomenti come keywords :Possono essere invocate usando gli argomenti come keywords : >>> info(cognome='Cuni', nome='Antonio') Cuni Antonio Funzioni possono avere una lista arbitraria di argomenti:Funzioni possono avere una lista arbitraria di argomenti: def foo(*arg, **keywords): def foo(*arg, **keywords): *arg è una tupla contenente i parametri posizionali **keywords è un dizionario dei keyword arguments a cui non corrisponde un parametro formale

Seminario IL Python Classi Definizione:Definizione: class ClassName: … Successivamente ad una definizione di classe si crea un class objectSuccessivamente ad una definizione di classe si crea un class object I class object supportano due operazioni:I class object supportano due operazioni: Riferimento agli attributi:Riferimento agli attributi: >>> class MyClass:... i = def f(self):... return 'hello world'... >>> MyClass.i >>> MyClass.f

Seminario IL Python Classi (2) Instanziazione (come una chiamata di funzione senza parametri che restituisce un’istanza):Instanziazione (come una chiamata di funzione senza parametri che restituisce un’istanza): x = MyClass() Per inserire uno stato iniziale bisogna definire il metodo __init__:Per inserire uno stato iniziale bisogna definire il metodo __init__: >>> class Complex:... def __init__(self, realpart, imagpart):... self.r = realpart... self.i = imagpart... >>> x = Complex(3.0, -4.5) >>> x.r, x.i (3.0, -4.5) Gli attributi sono creati la prima volta che gli viene assegnato un valoreGli attributi sono creati la prima volta che gli viene assegnato un valore La chiamata di metodo passa implicitamente l’istanza dell’oggetto come primo argomento:La chiamata di metodo passa implicitamente l’istanza dell’oggetto come primo argomento: x.f() è perfettamente equivalente a MyClass.f(x)

Seminario IL Python Class Inheritance Sintassi:Sintassi: class DerivedClassName(BaseClassName): … … Se BaseClass non è nello stesso modulo:Se BaseClass non è nello stesso modulo: class DerivedClassName(modname.BaseClassName): super(type,[object-or-type]) ritorna la superclasse di type:super(type,[object-or-type]) ritorna la superclasse di type: class C(B): def meth(self, arg): def meth(self, arg): super(C, self).meth(arg) super(C, self).meth(arg) Supporta ereditarietà multipla:Supporta ereditarietà multipla: class DerivedClassName(Base1, Base2, Base3): risoluzione attributi depht-first, left-to-right

Seminario IL 3. Implementazione degli oggetti in Python

Seminario IL Oggetti e nomi In Python ogni oggetto risiede in un “universo” di oggetti e ha una identità distinta.In Python ogni oggetto risiede in un “universo” di oggetti e ha una identità distinta. Noi ci riferiamo agli oggetti dei nomi che si riferiscono ad essi.Noi ci riferiamo agli oggetti dei nomi che si riferiscono ad essi. I nomi degli oggetti sono raggruppati in namespaces.I nomi degli oggetti sono raggruppati in namespaces. Quando un oggetto non è più riferito da alcun nome, viene raccolto dal garbage collector.Quando un oggetto non è più riferito da alcun nome, viene raccolto dal garbage collector. x z y w Universo degli oggetti Namespace dei nomi

Seminario IL Binding di un oggetto Il binding è quel meccanismo che associa un nome ad un oggetto.Il binding è quel meccanismo che associa un nome ad un oggetto. Esso è realizzato dall’operatore =Esso è realizzato dall’operatore = Quando assegniamo un valore ad una variabile, in realtà stiamo legando un nome ad un oggetto.Quando assegniamo un valore ad una variabile, in realtà stiamo legando un nome ad un oggetto. x y ‘ciao’ ‘salve’ x = ‘ciao’ y = x x = ‘salve’

Seminario IL Tutto è un oggetto Tutto quello a cui ci possiamo riferire con un nome è un oggetto:Tutto quello a cui ci possiamo riferire con un nome è un oggetto: Numeri, stringhe, liste, funzioni, classi, ecc. sono tutti oggetti.Numeri, stringhe, liste, funzioni, classi, ecc. sono tutti oggetti. Tutti gli oggetti sono first class value: ad esempio possono essere passati come argomenti alle funzioni.Tutti gli oggetti sono first class value: ad esempio possono essere passati come argomenti alle funzioni. >>> def somma(a, b): return a + b... >>> def applica(funzione, a, b):... return funzione(a,b)... >>> applica(somma, 3, 5) 8

Seminario IL Proprietà di un oggetto Da un punto di vista astratto, un oggetto possiede due proprietà:Da un punto di vista astratto, un oggetto possiede due proprietà: Uno stato, che rappresenta il valore attuale assunto dall’oggetto.Uno stato, che rappresenta il valore attuale assunto dall’oggetto. Un tipo, che identifica le operazioni che possono essere compiute sull’oggetto.Un tipo, che identifica le operazioni che possono essere compiute sull’oggetto. Alcuni tipi sono immutabili: questo significa che un oggetto di tale tipo non potrà mai cambiare stato.Alcuni tipi sono immutabili: questo significa che un oggetto di tale tipo non potrà mai cambiare stato. Es.: numeri, stringhe, tuple Altri tipi sono mutabili, ovvero lo stato dei rispettivi oggetti può cambiare.Altri tipi sono mutabili, ovvero lo stato dei rispettivi oggetti può cambiare. Es.: liste, dizionari

Seminario IL Layout degli oggetti La principale implementazione di Python è scritta in C ed è chiamata CPython.La principale implementazione di Python è scritta in C ed è chiamata CPython. Ogni oggetto di Python è rappresentato da una struct del C.Ogni oggetto di Python è rappresentato da una struct del C. Tali struct sono composte da una serie di campi; ad esempio:Tali struct sono composte da una serie di campi; ad esempio: Reference count (per la gestione della memoria)Reference count (per la gestione della memoria) Puntatore al tipo dell’oggetto (che a sua volta sarà rappresentato da una struct.Puntatore al tipo dell’oggetto (che a sua volta sarà rappresentato da una struct. Campi che memorizzano lo stato.Campi che memorizzano lo stato.

Seminario IL Esempio Segue la definizione della struttura PyIntObject, che rappresenta un numero intero.Segue la definizione della struttura PyIntObject, che rappresenta un numero intero. typedef struct { int ob_refcnt; int ob_refcnt; struct _typeobject *ob_type; struct _typeobject *ob_type; long ob_ival; long ob_ival; } PyIntObject; Possiamo notare la presenza di tre campi:Possiamo notare la presenza di tre campi: ob_refcnt memorizza il reference count;ob_refcnt memorizza il reference count; ob_type punta al tipo (che sarà PyInt_Type);ob_type punta al tipo (che sarà PyInt_Type); ob_ival memorizza il valore vero e proprio del numero.ob_ival memorizza il valore vero e proprio del numero.

Seminario IL Layout dei tipi In Python anche i tipi sono oggetti ed anch’essi sono rappresentati da una struct.In Python anche i tipi sono oggetti ed anch’essi sono rappresentati da una struct. Oltre ai campi precedenti, le struct dei tipi contengono anche una serie di puntatori a funzione che identificano alcune operazioni “standard”.Oltre ai campi precedenti, le struct dei tipi contengono anche una serie di puntatori a funzione che identificano alcune operazioni “standard”. Ad esempio le struct dei tipi numerici contengono puntatori a funzioni che servono a fare addizioni, sottrazioni, ecc.Ad esempio le struct dei tipi numerici contengono puntatori a funzioni che servono a fare addizioni, sottrazioni, ecc.

Seminario IL Attributi degli oggetti La maggior parte degli oggetti possiede anche un dizionario, che mappa la corrispondenza tra i nomi e i valori degli attributi.La maggior parte degli oggetti possiede anche un dizionario, che mappa la corrispondenza tra i nomi e i valori degli attributi. Esempio:Esempio: class MiaClasse: def __init__(self): def __init__(self): self.x = ‘ciao’ self.x = ‘ciao’ def saluta(self): def saluta(self): print self.x print self.x mioOggetto = MiaClasse()

Seminario IL Esempio struct PyTypeObject { char* tp_name = “MiaClasse”; PyObject* tp_dict;... } PyDictObject: ‘__init__’ ‘saluta’ ‘__dict__’ PyMethodObject: self.x = ‘ciao’ PyMethodObject: print self.x struct PyInstanceObject { PyObject* in_type; PyObject* in_dict;... } PyDictObject: ‘__class__’ ‘x’ ‘__dict__’ PyStringObject: ‘ciao’ class MiaClasse: mioOggetto = MiaClasse()

Seminario IL Lookup degli attributi Il meccanismo di lookup degli attributi è il concetto centrale degli oggetti di Python.Il meccanismo di lookup degli attributi è il concetto centrale degli oggetti di Python. Esso è progettato in modo tale che alcune idee centrali del mondo OO diventano quasi automatiche:Esso è progettato in modo tale che alcune idee centrali del mondo OO diventano quasi automatiche: Differenza tra campi (che si riferiscono ad un oggetto) e metodi (che si riferiscono al suo tipo o classe).Differenza tra campi (che si riferiscono ad un oggetto) e metodi (che si riferiscono al suo tipo o classe). Ereditarietà singola e multiplaEreditarietà singola e multipla PolimorfismoPolimorfismo Metodi e attributi statici e di classe.Metodi e attributi statici e di classe. ProprietàProprietà

Seminario IL Regole di lookup (semplificate) Supponiamo di avere un oggetto obj e di voler accedere ad un attributo di nome “x”:Supponiamo di avere un oggetto obj e di voler accedere ad un attributo di nome “x”: 1.Controllo il nome “x” è presente nel dizionario di obj (obj.__dict__). 2.Se non c’è controllo se “x” è presente nel dizionario del tipo di obj (obj.__class__.__dict__) 3.Se non c’è controllo il dizionario di tutte le classi base (le basi di una classe C sono elencate nell’attributo C.__bases__).

Seminario IL Regole di lookup: esempio class Base: def __init__(self, nome): def __init__(self, nome): self.nome = nome self.nome = nome def saluta(self): def saluta(self): print ‘ciao’, self.nome print ‘ciao’, self.nome class Derivata(Base): def saluta(self): def saluta(self): print ‘Buongiorno’, self.nome print ‘Buongiorno’, self.nome obj = Derivata(‘anto’)

Seminario IL Regole di lookup: esempio Base __bases__ __init__ saluta Derivata __bases__ saluta obj __class__ name Lookup di obj.X Controllo obj.__dict__Controllo obj.__dict__ Controllo obj.__class__.__dict__Controllo obj.__class__.__dict__ Controllo tutte le classi in obj.__class__.__bases__Controllo tutte le classi in obj.__class__.__bases__ Lookup di obj.nameLookup di obj.name Lookup di obj.salutaLookup di obj.saluta Lookup di obj.__init__Lookup di obj.__init__

Seminario IL Funzioni e metodi Abbiamo visto che le classi possono avere dei metodi.Abbiamo visto che le classi possono avere dei metodi. Internamente i metodi sono memorizzati come normalissime funzioni, ma con una differenza: il primo parametro (self) è passato automaticamente.Internamente i metodi sono memorizzati come normalissime funzioni, ma con una differenza: il primo parametro (self) è passato automaticamente. EsempioEsempio class MiaClasse: def mioMetodo(self, a): def mioMetodo(self, a): print a print a obj = MiaClasse() obj.mioMetodo(‘ciao’) Al momento della chiamata passo un solo argomento a mioMetodo, ma l’interprete ne aggiunge automaticamente uno (il self).Al momento della chiamata passo un solo argomento a mioMetodo, ma l’interprete ne aggiunge automaticamente uno (il self).

Seminario IL Bound methods Questo è possibile perché quando la procedura di lookup si accorge di aver trovato una funzione, la trasforma in un bound method.Questo è possibile perché quando la procedura di lookup si accorge di aver trovato una funzione, la trasforma in un bound method. I bound method sono delle funzioni che “si ricordano” a quale oggetto fanno riferimento: quando sono chiamati aggiungono automaticamente tale oggetto in cima alla lista degli argomenti.I bound method sono delle funzioni che “si ricordano” a quale oggetto fanno riferimento: quando sono chiamati aggiungono automaticamente tale oggetto in cima alla lista degli argomenti. L’effetto finale è che quando chiamiamo un metodo su un oggetto il parametro self è passato in modo automatico.L’effetto finale è che quando chiamiamo un metodo su un oggetto il parametro self è passato in modo automatico. I bound method sono oggetti come gli altri: posso anche memorizzarli in una variabile e chiamarli più tardi.I bound method sono oggetti come gli altri: posso anche memorizzarli in una variabile e chiamarli più tardi. >>> obj = MiaClasse() >>> obj.mioMetodo # nota: non è chiamato! > > >>> xxx = obj.mioMetodo >>> xxx(‘ciao’) >>> xxx(‘ciao’)ciao

Seminario IL Ereditarietà singola Abbiamo visto che se la procedura di lookup non trova un attributo cerca ricorsivamente nelle classi base.Abbiamo visto che se la procedura di lookup non trova un attributo cerca ricorsivamente nelle classi base. Questo ci consente di implementare “gratis” l’ereditarietà: tutto quel che dobbiamo fare è memorizzare nell’attributo __bases__ la nostra classe base, e la procedura di lookup farà il resto.Questo ci consente di implementare “gratis” l’ereditarietà: tutto quel che dobbiamo fare è memorizzare nell’attributo __bases__ la nostra classe base, e la procedura di lookup farà il resto.

Seminario IL Ereditarietà multipla In presenza di ereditarietà multipla le cose sono più complicate.In presenza di ereditarietà multipla le cose sono più complicate. Seguendo le regole appena descritte l’ordine di lookup di un attributo su uno StudenteLavoratore sarebbe:Seguendo le regole appena descritte l’ordine di lookup di un attributo su uno StudenteLavoratore sarebbe: StudenteLavoratore, Studente, Persona, Lavoratore, PersonaStudenteLavoratore, Studente, Persona, Lavoratore, Persona Persona LavoratoreStudente StudenteLavoratore In genere non è questo che vogliamo, perché altrimenti i metodi di Persona sovrascritti da Lavoratore non verrebbero mai chiamati.In genere non è questo che vogliamo, perché altrimenti i metodi di Persona sovrascritti da Lavoratore non verrebbero mai chiamati. Inoltre la classe Persona sarebbe controllata due volte.Inoltre la classe Persona sarebbe controllata due volte. Al momento della creazione della classe viene calcolato un ordine di lookup seguendo una visita in ampiezza del grafo di ereditarietà.Al momento della creazione della classe viene calcolato un ordine di lookup seguendo una visita in ampiezza del grafo di ereditarietà. Tale ordine è memorizzato nell’attributo __mro__ (Method Resolution Order) della classe, che viene usato dalla procedura di lookup per controllare le classi base.Tale ordine è memorizzato nell’attributo __mro__ (Method Resolution Order) della classe, che viene usato dalla procedura di lookup per controllare le classi base. Il MRO di StudenteLavoratore è:Il MRO di StudenteLavoratore è: StudenteLavoratore, Studente, Lavoratore, PersonaStudenteLavoratore, Studente, Lavoratore, Persona

Seminario IL Polimorfismo Python supporta un tipo particolare di polimorfismo, detto polimorfismo basato su signature.Python supporta un tipo particolare di polimorfismo, detto polimorfismo basato su signature. Quando il programmatore utilizza un oggetto, non si deve preoccupare di quale sia il suo tipo, ma deve limitarsi a pensare a quali operazioni esso supporta.Quando il programmatore utilizza un oggetto, non si deve preoccupare di quale sia il suo tipo, ma deve limitarsi a pensare a quali operazioni esso supporta. L’insieme delle operazioni supportate da un oggetto costituisce la sua signature.L’insieme delle operazioni supportate da un oggetto costituisce la sua signature. Se due oggetti hanno la stessa signature, posso usarli intercambiabilmente senza che il codice debba essere modificato, anche se non hanno alcuna relazione di tipo.Se due oggetti hanno la stessa signature, posso usarli intercambiabilmente senza che il codice debba essere modificato, anche se non hanno alcuna relazione di tipo. Questo tipo di polimorfismo è simile a quello che il C++ offre con i template, con la differenza che in Python avviene a runtime.Questo tipo di polimorfismo è simile a quello che il C++ offre con i template, con la differenza che in Python avviene a runtime. Il polimorfismo basato su signature offre numerosi vantaggi, tra cui il fatto che il codice scritto è intrisecamente generico, cioè può operare su qualsiasi oggetto, anche se di tipo diverso.Il polimorfismo basato su signature offre numerosi vantaggi, tra cui il fatto che il codice scritto è intrisecamente generico, cioè può operare su qualsiasi oggetto, anche se di tipo diverso. Altri comuni linguaggi (es. C++, Java, C#) offrono invece un polimorfismo basato su interfaccia: questo significa che una funzione può operare solo su oggetti di un certo tipo o di un tipo derivato da esso.Altri comuni linguaggi (es. C++, Java, C#) offrono invece un polimorfismo basato su interfaccia: questo significa che una funzione può operare solo su oggetti di un certo tipo o di un tipo derivato da esso.

Seminario IL Esempio di polimorfismo >>> class Classe1:... def saluta(self): print 'ciao'... >>> class Classe2:... def saluta(self): print 'salve'... >>> def miaFunzione(obj):... obj.saluta()... >>> c1 = Classe1() >>> c2 = Classe2() >>> >>> miaFunzione(c1) ciao >>> miaFunzione(c2) salve

Seminario IL Creazione delle classi In Python tutto, comprese le classi, è un oggetto.In Python tutto, comprese le classi, è un oggetto. Il tipo di una generica classe è type.Il tipo di una generica classe è type. Quando definiamo una classe non facciamo altro che creare una istanza di type!Quando definiamo una classe non facciamo altro che creare una istanza di type! Il costruttore di type vuole tre parametri: il nome della classe, l’elenco delle sue basi e il dizionario dei suoi attributi.Il costruttore di type vuole tre parametri: il nome della classe, l’elenco delle sue basi e il dizionario dei suoi attributi. Il dizionario degli attributi non è altro che un normalissimo dizionario in cui ad ogni nome di attributo corrisponde il suo valore (normalmente sarà una funzione).Il dizionario degli attributi non è altro che un normalissimo dizionario in cui ad ogni nome di attributo corrisponde il suo valore (normalmente sarà una funzione). Nell’esempio a fianco:Nell’esempio a fianco: Il nome della classe è la stringa ‘A’Il nome della classe è la stringa ‘A’ L’elenco delle basi è la tupla (B,C)L’elenco delle basi è la tupla (B,C) Il dizionario degli attributi contiene le chiavi ‘metodo1’ e ‘metodo2’Il dizionario degli attributi contiene le chiavi ‘metodo1’ e ‘metodo2’ class A(B,C): def metodo1(self): def metodo1(self): print ‘ciao’ print ‘ciao’ def metodo2(self): def metodo2(self): print ‘salve’ print ‘salve’ A = type(‘A’, (B,C), {‘metodo1’: …,‘metodo2’:… })A = type(‘A’, (B,C), {‘metodo1’: …,‘metodo2’:… })

Seminario IL Creazione delle classi >>> def __init__(self, nome):... self.nome = nome... >>> def saluta(self):... print ‘ciao’, self.nome... >>> attributi = {'__init__': __init__, 'saluta': saluta} >>> MiaClasse = type('MiaClasse', (), attributi) >>> >>> obj = MiaClasse('anto') >>> obj.saluta() ciao anto

Seminario IL Implementazione del lookup L’interprete Python è basato su una macchina astratta.L’interprete Python è basato su una macchina astratta. Per vedere come è implementato il meccanismo di lookup possiamo iniziare ad esaminare il bytecode eseguito da tale macchina.Per vedere come è implementato il meccanismo di lookup possiamo iniziare ad esaminare il bytecode eseguito da tale macchina. Il modulo standard dis serve a disassemblare il bytecode.Il modulo standard dis serve a disassemblare il bytecode. >>> import dis >>> def prova(x):... return x.attributo... >>> dis.dis(prova) 0 SET_LINENO 1 0 SET_LINENO 1 3 SET_LINENO 2 3 SET_LINENO 2 6 LOAD_FAST 0 (x) 6 LOAD_FAST 0 (x) 9 LOAD_ATTR 1 (attributo) 9 LOAD_ATTR 1 (attributo) 12 RETURN_VALUE 12 RETURN_VALUE

Seminario IL L’opcode LOAD_ATTR L’opcode della macchina che si occupa di eseguire un lookup è LOAD_ATTR.L’opcode della macchina che si occupa di eseguire un lookup è LOAD_ATTR. Esaminiamo il sorgente C della macchina virtuale; questo è il main loop:Esaminiamo il sorgente C della macchina virtuale; questo è il main loop: switch (opcode) { case LOAD_FAST:... case LOAD_CONST:... case LOAD_ATTR: w = GETITEM(names, oparg); v = TOP(); x = PyObject_GetAttr(v, w); Py_DECREF(v);SET_TOP(x); if (x != NULL) continue; break;...}

Seminario IL PyObject_GetAttr A questo punto possiamo esaminare la funzione PyObject_GetAttr, definita in Objects/object.c:A questo punto possiamo esaminare la funzione PyObject_GetAttr, definita in Objects/object.c: PyObject * PyObject_GetAttr(PyObject *v, PyObject *name) { PyTypeObject *tp = v->ob_type;... if (tp->tp_getattro != NULL) return (*tp->tp_getattro)(v, name);...}

Seminario IL Il campo tp_getattro Esaminando il codice precedente possiamo notare una cosa importante: la funzione che esegue il lookup vero e proprio non è univoca, ma dipende dal tipo dell’oggetto.Esaminando il codice precedente possiamo notare una cosa importante: la funzione che esegue il lookup vero e proprio non è univoca, ma dipende dal tipo dell’oggetto. Ogni tipo ha un campo tp_getattro che contiene un puntatore ad una funzione che esegue il lookup.Ogni tipo ha un campo tp_getattro che contiene un puntatore ad una funzione che esegue il lookup. Questo significa che se quella di default non ci soddisfa possiamo anche definire una nostra politica di lookup.Questo significa che se quella di default non ci soddisfa possiamo anche definire una nostra politica di lookup. Il campo tp_getattro della struct PyType_Type punta alla funzione type_getattro, definita in Objects/typeobject.c: tale funzione implementa la politica di lookup vista in precedenza.Il campo tp_getattro della struct PyType_Type punta alla funzione type_getattro, definita in Objects/typeobject.c: tale funzione implementa la politica di lookup vista in precedenza. Ai margini è interessante notare come, in pratica, gli sviluppatori di Python hanno implementato in C un meccanismo di dispatching simile a quello delle funzioni virtuali presenti in altri linguaggi.Ai margini è interessante notare come, in pratica, gli sviluppatori di Python hanno implementato in C un meccanismo di dispatching simile a quello delle funzioni virtuali presenti in altri linguaggi.

Seminario IL Cenni sul descriptor protocol In realtà l’implementazione di Python è leggermente più complessa di quanto abbiamo visto fin’ora.In realtà l’implementazione di Python è leggermente più complessa di quanto abbiamo visto fin’ora. Prima di continuare, definiamo un nuovo termine:Prima di continuare, definiamo un nuovo termine: Un descrittore è un oggetto che possiede un metodo __get__ (e opzionalmente un metodo __set__)Un descrittore è un oggetto che possiede un metodo __get__ (e opzionalmente un metodo __set__) Durante il lookup di un attributo, prima di restituire l’oggetto corrispondente controlliamo se quest’ultimo è un descrittore.Durante il lookup di un attributo, prima di restituire l’oggetto corrispondente controlliamo se quest’ultimo è un descrittore. Se l’oggetto è un descrittore, chiamiamo il suo metodo __get__ (o __set__, a seconda dei casi) e restituiamo il risultato.Se l’oggetto è un descrittore, chiamiamo il suo metodo __get__ (o __set__, a seconda dei casi) e restituiamo il risultato. Questo meccanismo consente agli oggetti di controllare la modalità con cui possono essere acceduti.Questo meccanismo consente agli oggetti di controllare la modalità con cui possono essere acceduti.

Seminario IL Esempio di descrittore Senza saperlo, abbiamo già visto un esempio di descrittore: le funzioni.Senza saperlo, abbiamo già visto un esempio di descrittore: le funzioni. Le funzioni hanno un metodo __get__: se esso si accorge che stiamo facendo il lookup su una istanza di classe, costruisce al volo un bound method e lo restituisce.Le funzioni hanno un metodo __get__: se esso si accorge che stiamo facendo il lookup su una istanza di classe, costruisce al volo un bound method e lo restituisce. In genere il metodo __get__ viene chiamato automaticamente dall’interprete, ma possiamo anche farlo “a mano”:In genere il metodo __get__ viene chiamato automaticamente dall’interprete, ma possiamo anche farlo “a mano”: >>> def somma(a, b): return a+b... >>> dummyMethod = somma.__get__(3) >>> dummyMethod >>> dummyMethod(5) 8 In questo esempio abbiamo “fatto credere” a somma di essere un metodo dell’oggetto 3. Quando richiamiamo il metodo il primo parametro (3) è aggiunto automaticamente.In questo esempio abbiamo “fatto credere” a somma di essere un metodo dell’oggetto 3. Quando richiamiamo il metodo il primo parametro (3) è aggiunto automaticamente.

Seminario IL Altri descrittori utili Il descriptor protocol è un meccanismo fondamentale per implementare alcuni costrutti OO; ecco alcuni esempi:Il descriptor protocol è un meccanismo fondamentale per implementare alcuni costrutti OO; ecco alcuni esempi: staticmethod: è un tipo il cui costruttore prende una funzione e restituisce un descrittore che, al contrario delle normali funzioni, non le trasforma in bound method. Questo consente di ottenere dei metodi statici.staticmethod: è un tipo il cui costruttore prende una funzione e restituisce un descrittore che, al contrario delle normali funzioni, non le trasforma in bound method. Questo consente di ottenere dei metodi statici. classmethod: è un tipo il cui costruttore prende una funzione e restituisce un descrittore che, quando acceduto, lega una funzione alla classe dell’istanza di provenienza. Questo consente di ottenere dei metodi di classe.classmethod: è un tipo il cui costruttore prende una funzione e restituisce un descrittore che, quando acceduto, lega una funzione alla classe dell’istanza di provenienza. Questo consente di ottenere dei metodi di classe. property: questo tipo accetta come parametri due funzioni: un “getter” e un “setter”: restituisce un oggetto che quando viene acceduto inoltra la richiesta al getter o al setter, a seconda dei casi. Questo consente di implementare le proprietà: agli occhi dell’utente appaiono come normali attributi, ma in realtà quando vengono accedute vengono automaticamente chiamate dei metodi “trigger”.property: questo tipo accetta come parametri due funzioni: un “getter” e un “setter”: restituisce un oggetto che quando viene acceduto inoltra la richiesta al getter o al setter, a seconda dei casi. Questo consente di implementare le proprietà: agli occhi dell’utente appaiono come normali attributi, ma in realtà quando vengono accedute vengono automaticamente chiamate dei metodi “trigger”.

Seminario IL Metaclassi Come tutti gli oggetti, anche le classi hanno un tipo: esso è chiamato metaclasse (la “classe della classe”).Come tutti gli oggetti, anche le classi hanno un tipo: esso è chiamato metaclasse (la “classe della classe”). Abbiamo visto che quando definiamo una classe, l’interprete crea una istanza di type: in questo caso, type è proprio la metaclasse.Abbiamo visto che quando definiamo una classe, l’interprete crea una istanza di type: in questo caso, type è proprio la metaclasse. Possiamo anche definire delle metaclassi alternative da usare al posto di type: con esse possiamo alterare il normale funzionamento delle istanze.Possiamo anche definire delle metaclassi alternative da usare al posto di type: con esse possiamo alterare il normale funzionamento delle istanze. Ecco alcuni esempi di possibili metaclassi:Ecco alcuni esempi di possibili metaclassi: readonly: le classi istanziate potranno avere solo attributi read-onlyreadonly: le classi istanziate potranno avere solo attributi read-only interface: tutti i metodi delle classi istanziati dovranno essere astrattiinterface: tutti i metodi delle classi istanziati dovranno essere astratti monitor: le classi istanziate si comporteranno come un monitormonitor: le classi istanziate si comporteranno come un monitor Per determinare la metaclasse da usare, l’interprete guarda se nel dizionario è presente l’attributo __metaclass__; altrimenti usa la metaclasse di default.Per determinare la metaclasse da usare, l’interprete guarda se nel dizionario è presente l’attributo __metaclass__; altrimenti usa la metaclasse di default. Abbiamo barato ! In tutti gli esempi che abbiamo fatto fin’ora, abbiamo assunto che la metaclasse di default fosse proprio type.Abbiamo barato ! In tutti gli esempi che abbiamo fatto fin’ora, abbiamo assunto che la metaclasse di default fosse proprio type. In realtà questo non è vero, per ragioni di compatibilità con versioni di Python precedenti alla 2.2.In realtà questo non è vero, per ragioni di compatibilità con versioni di Python precedenti alla 2.2.