Parte 2




      Programmazione ad oggetti
             in Python




Linguaggi dinamici – A.A. 2009/2010
                                      1
Introduzione
„   Unità fondamentale degli oggetti: classe
      „   Contenitore di variabili (attributi) e funzioni
          (metodi)
„   Strumenti a di
    St     ti disposizione della OOP
                    i i    d ll
      „   Astrazione: capacità di ridurre il numero di
          dettagli implementativi
          d     li i l         i i
      „   Incapsulamento: capacità di nascondere i
          dettagli ai moduli esterni
      „   Ereditarietà: capacità di perfezionare il
          comportamento di una classe
      „   Polimorfismo: capacità di adattare il
          comportamento in funzione di ingressi e uscita
Linguaggi dinamici – A.A. 2009/2010
                                                            2
Definizione di classe in Python
„   Una classe è definita all'interno di un modulo,
    tramite lo statement class
class ClassName:
   <statement 1>
   < t t     t
   …
   <statement n>
„ Solitamente, gli statement sono definizioni di
  funzioni (ma non è necessariamente detto)
„ La definizione di una classe crea un nuovo
  namespace, che viene usato come lo scope della
  classe (variabili locali)

Linguaggi dinamici – A.A. 2009/2010
                                                      3
Oggetti “classe”
„   Al termine della definizione di una classe,
    l interprete
    l'interprete crea un oggetto di tipo classe
„   Tale oggetto abilita due operazioni:
      „   Attribute f
          Att ib t reference: permette l'
                                      tt l'accesso aglili
          elementi di una classe (attributi e metodi),
          tramite la sintassi NomeClasse nome elemento
                              NomeClasse.nome_elemento
      „   Instantiation: permette la creazione di istanze di
          classe (oggetti) tramite la notazione funzionale
          variabile = NomeClasse()
„   L'istanziazione si preoccupa di invocare il
    L'i t   i i      i              i
    metodo costruttore della classe

Linguaggi dinamici – A.A. 2009/2010
                                                               4
Creazione di un oggetto
„   Un oggetto viene creato “chiamando” la classe
     „   o = MyClass()
„   Alla variabile o viene assegnato un riferimento
    ad un oggetto di classe MyClass
„   Ricordarsi di importare il nome della classe se
    è definito in un namespace diverso
„   Ad es., se MyClass è definita nel file
    MyClass.py
    M Cl
     „   from MyClass import MyClass


               namespace
                    p                 classe

Linguaggi dinamici – A.A. 2009/2010
                                                      5
ÆESEMPI

                      Il metodo costruttore
                                                      Bag.py
                                                   Complex.py


„   Il metodo costruttore di una classe ha il nome
    __init__, e viene invocato automaticamente in
       init
    seguito all'istanziazione di una classe
„   Il metodo __init__, per il resto, gode di tutte le
                  init         resto
    proprietà delle funzioni
      „   Argomenti con nome
          A      ti
      „   Argomenti di default
„   C’è sempre un argomento implicito che
    rappresenta l’oggetto
„   Lo stato interno di un oggetto è dichiarato
    tramite opportune strutture dati
             pp
Linguaggi dinamici – A.A. 2009/2010
                                                            6
ÆESEMPI

                             Attributi di dati
                                                       Complex2.py



„ Il Python permette la creazione automatica di
  attributi all interno di un oggetto, tramite
            all'interno       oggetto
  semplici operazioni di assegnazione
„ Ad esempio, posso creare un attributo counter
      esempio
  al volo su un oggetto x:
x.counter = 1
        t
„ counter viene trattato alla stregua di una

  variabile di appoggio, valida solo per l'istanza
  x
      „   Quando x viene distrutto, counter sparisce
      „   counter può essere distrutto con del
                  p
Linguaggi dinamici – A.A. 2009/2010
                                                                 7
Metodi
„  È possibile invocare i metodi di un oggetto o di
   una classe con la notazione .
risultato = oggetto.metodo(argomenti)
„ Il primo argomento di ogni metodo, che viene
       i            t        i   t d    h i
   passato implicitamente dall'interprete, è
      „   la reference all'oggetto istanza, se il metodo è
          stato invocato tramite un'istanza
      „   la reference all'oggetto classe, se il metodo è
          stato invocato tramite la classe
„   Per convenzione, il primo argomento viene
    nominato self
Linguaggi dinamici – A.A. 2009/2010
                                                             8
Metodi
„   Si noti che la chiamata
     „   x = MyClass()
     „   x.m()
„   corrisponde a:
        i    d
     „   MyClass.m(x)
„   E in effetti il metodo è definito così:
     „   class MyClass:
         „  def m(self):
         „  …



Linguaggi dinamici – A.A. 2009/2010
                                               9
ÆESEMPI

                                      Metodi
                                                   C.py



„   È anche possibile sfruttare funzioni definite
    fuori dalla classe
„   Attraverso una variabile della classe che
    rappresenta la funzione esterna
„   È valido anche per metodi definiti internamente
    alla classe




Linguaggi dinamici – A.A. 2009/2010
                                                      10
Distruttori
„   In maniera simile al Perl, è previsto un
    meccanismo di reference counting degli
    oggetti
„   Si invoca la procedura di distruzione quando:
      „   il reference count di un oggetto diventa nullo
      „   si invoca il metodo del() sull'oggetto
            ii             d d l() ll'
„   Procedura di distruzione: l'interprete invoca il
    metodo privato __del__() dell'oggetto (che sia
    definito nell'oggetto stesso o ereditato da una
    superclasse)


Linguaggi dinamici – A.A. 2009/2010
                                                           11
ÆESEMPI

                                 Ereditarietà
                                                Ereditarieta.py



„   Una classe può ereditare da un'altra classe
    con la seguente sintassi:
class DerivedClassName(BaseClassName):
  <statement 1>
  < t t     t
  …
  <statement n>
„   È possibile usare il nome completo della
      p                            p
    superclasse (comodo nelle situazioni in cui la
    superclasse è definita in un altro file)
       p                                   )
„   Altrimenti ricordarsi di importare la classe dal
    modulo
Linguaggi dinamici – A.A. 2009/2010
                                                            12
Ereditarietà multipla
„   Una classe può ereditare da più classi con la
    seguente sintassi:
class DerivedClassName(C1, C2, C3):
   <statement 1>
   < t t    t
   …
   <statement n>
„   È possibile usare il nome completo delle
        p                           p
    superclassi
 „ La ricerca di un elemento non in C avviene per

    profondità prima in C1 (e superclassi), poi in
    C2 (e superclassi), e infine in C3 (e
    superclassi)
Linguaggi dinamici – A.A. 2009/2010
                                                     13
Funzioni relative all’ereditarietà
„   Il Python definisce due funzioni nel contesto
    dell ereditarietà
    dell'ereditarietà
     „ isinstance(obj, objtype): ritorna True se obj

       è un'istanza della classe objtype
         un istanza
     „ issubclass(obj, objtype): ritorna True se obj

       è una sottoclasse di objtype
                tt l          bjt




Linguaggi dinamici – A.A. 2009/2010
                                                       14
Polimorfismo
„ È sufficiente ridefinire un metodo all'interno di
  una sottoclasse per sostituirlo alle definizioni
  presenti nelle superclassi
„ L'interprete Python gestisce il polimorfismo
  L interprete
  automaticamente, andandosi a cercare il
  metodo con la signature adatta
„ All'interno di un metodo ridefinito nella

  sottoclasse, è possibile invocare il metodo
     tt l              ibil i              t d
  della superclasse con la seguente sintassi:
BaseClassName.methodname(self, arguments)


Linguaggi dinamici – A.A. 2009/2010
                                                      15
ÆESEMPI

                            Variabili private
                                                  Private.py



„   Ogni identificatore (variabile, metodo) __ident_
    con almeno due underscore davanti ed al più
    un underscore dietro viene rinominato
    internamente in _c ass a e__ident, dove
      te a e te       classname de t, do e
    classname è il nome della classe corrente
    senza gli underscore iniziali
          g




Linguaggi dinamici – A.A. 2009/2010
                                                         16
Vecchio e nuovo stile della POO
„   Nel vecchio stile:
     „   Le classi sono oggetti
     „   La ricerca di attributi avviene con un algoritmo
         statico (depth-first left-to-right)
                 (depth-first,
„   Nel nuovo stile:
     „   Le l
         L classi sono ti i
                  i      tipi
     „   La ricerca di attributi avviene in modo dinamico
     „   La gerarchia ha una radice: object
„   Il nuovo stile gestisce meglio casi di eredità “a
    diamante”, in cui la stessa superclasse è
    raggiungibile tramite percorsi diversi

Linguaggi dinamici – A.A. 2009/2010
                                                            17
ÆESEMPI

                                      super
                                                    Counter.py
                                                   Counter2.py


„   In Python non c’è il concetto di super
     „   Mancanza dovuta anche alla presenza di
         ereditarietà multipla
„   Esiste però la funzione super(type object) che
                              super(type,
    restituisce il “super tipo” della classe corrente
„   Funziona solo con il nuovo stile di classi
„   È necessario che all’apice della gerarchia ci
    sia object




Linguaggi dinamici – A.A. 2009/2010
                                                           18
ÆESEMPI

                                      Iteratori
                                                        Reverse.py



„   Il metodo __iter__ definisce un iteratore per la
    classe corrente
     „ Tale oggetto deve contenere un metodo

       next()
„   Il metodo next definisce lo step di iterazione
      „   Seleziona un elemento diverso ad ogni
          invocazione
      „   Solleva una eccezione di tipo StopIteration
          quando tutti gli elementi sono stati selezionati



Linguaggi dinamici – A.A. 2009/2010
                                                               19

Py t3 python-oggetti

  • 1.
    Parte 2 Programmazione ad oggetti in Python Linguaggi dinamici – A.A. 2009/2010 1
  • 2.
    Introduzione „ Unità fondamentale degli oggetti: classe „ Contenitore di variabili (attributi) e funzioni (metodi) „ Strumenti a di St ti disposizione della OOP i i d ll „ Astrazione: capacità di ridurre il numero di dettagli implementativi d li i l i i „ Incapsulamento: capacità di nascondere i dettagli ai moduli esterni „ Ereditarietà: capacità di perfezionare il comportamento di una classe „ Polimorfismo: capacità di adattare il comportamento in funzione di ingressi e uscita Linguaggi dinamici – A.A. 2009/2010 2
  • 3.
    Definizione di classein Python „ Una classe è definita all'interno di un modulo, tramite lo statement class class ClassName: <statement 1> < t t t … <statement n> „ Solitamente, gli statement sono definizioni di funzioni (ma non è necessariamente detto) „ La definizione di una classe crea un nuovo namespace, che viene usato come lo scope della classe (variabili locali) Linguaggi dinamici – A.A. 2009/2010 3
  • 4.
    Oggetti “classe” „ Al termine della definizione di una classe, l interprete l'interprete crea un oggetto di tipo classe „ Tale oggetto abilita due operazioni: „ Attribute f Att ib t reference: permette l' tt l'accesso aglili elementi di una classe (attributi e metodi), tramite la sintassi NomeClasse nome elemento NomeClasse.nome_elemento „ Instantiation: permette la creazione di istanze di classe (oggetti) tramite la notazione funzionale variabile = NomeClasse() „ L'istanziazione si preoccupa di invocare il L'i t i i i i metodo costruttore della classe Linguaggi dinamici – A.A. 2009/2010 4
  • 5.
    Creazione di unoggetto „ Un oggetto viene creato “chiamando” la classe „ o = MyClass() „ Alla variabile o viene assegnato un riferimento ad un oggetto di classe MyClass „ Ricordarsi di importare il nome della classe se è definito in un namespace diverso „ Ad es., se MyClass è definita nel file MyClass.py M Cl „ from MyClass import MyClass namespace p classe Linguaggi dinamici – A.A. 2009/2010 5
  • 6.
    ÆESEMPI Il metodo costruttore Bag.py Complex.py „ Il metodo costruttore di una classe ha il nome __init__, e viene invocato automaticamente in init seguito all'istanziazione di una classe „ Il metodo __init__, per il resto, gode di tutte le init resto proprietà delle funzioni „ Argomenti con nome A ti „ Argomenti di default „ C’è sempre un argomento implicito che rappresenta l’oggetto „ Lo stato interno di un oggetto è dichiarato tramite opportune strutture dati pp Linguaggi dinamici – A.A. 2009/2010 6
  • 7.
    ÆESEMPI Attributi di dati Complex2.py „ Il Python permette la creazione automatica di attributi all interno di un oggetto, tramite all'interno oggetto semplici operazioni di assegnazione „ Ad esempio, posso creare un attributo counter esempio al volo su un oggetto x: x.counter = 1 t „ counter viene trattato alla stregua di una variabile di appoggio, valida solo per l'istanza x „ Quando x viene distrutto, counter sparisce „ counter può essere distrutto con del p Linguaggi dinamici – A.A. 2009/2010 7
  • 8.
    Metodi „ Èpossibile invocare i metodi di un oggetto o di una classe con la notazione . risultato = oggetto.metodo(argomenti) „ Il primo argomento di ogni metodo, che viene i t i t d h i passato implicitamente dall'interprete, è „ la reference all'oggetto istanza, se il metodo è stato invocato tramite un'istanza „ la reference all'oggetto classe, se il metodo è stato invocato tramite la classe „ Per convenzione, il primo argomento viene nominato self Linguaggi dinamici – A.A. 2009/2010 8
  • 9.
    Metodi „ Si noti che la chiamata „ x = MyClass() „ x.m() „ corrisponde a: i d „ MyClass.m(x) „ E in effetti il metodo è definito così: „ class MyClass: „ def m(self): „ … Linguaggi dinamici – A.A. 2009/2010 9
  • 10.
    ÆESEMPI Metodi C.py „ È anche possibile sfruttare funzioni definite fuori dalla classe „ Attraverso una variabile della classe che rappresenta la funzione esterna „ È valido anche per metodi definiti internamente alla classe Linguaggi dinamici – A.A. 2009/2010 10
  • 11.
    Distruttori „ In maniera simile al Perl, è previsto un meccanismo di reference counting degli oggetti „ Si invoca la procedura di distruzione quando: „ il reference count di un oggetto diventa nullo „ si invoca il metodo del() sull'oggetto ii d d l() ll' „ Procedura di distruzione: l'interprete invoca il metodo privato __del__() dell'oggetto (che sia definito nell'oggetto stesso o ereditato da una superclasse) Linguaggi dinamici – A.A. 2009/2010 11
  • 12.
    ÆESEMPI Ereditarietà Ereditarieta.py „ Una classe può ereditare da un'altra classe con la seguente sintassi: class DerivedClassName(BaseClassName): <statement 1> < t t t … <statement n> „ È possibile usare il nome completo della p p superclasse (comodo nelle situazioni in cui la superclasse è definita in un altro file) p ) „ Altrimenti ricordarsi di importare la classe dal modulo Linguaggi dinamici – A.A. 2009/2010 12
  • 13.
    Ereditarietà multipla „ Una classe può ereditare da più classi con la seguente sintassi: class DerivedClassName(C1, C2, C3): <statement 1> < t t t … <statement n> „ È possibile usare il nome completo delle p p superclassi „ La ricerca di un elemento non in C avviene per profondità prima in C1 (e superclassi), poi in C2 (e superclassi), e infine in C3 (e superclassi) Linguaggi dinamici – A.A. 2009/2010 13
  • 14.
    Funzioni relative all’ereditarietà „ Il Python definisce due funzioni nel contesto dell ereditarietà dell'ereditarietà „ isinstance(obj, objtype): ritorna True se obj è un'istanza della classe objtype un istanza „ issubclass(obj, objtype): ritorna True se obj è una sottoclasse di objtype tt l bjt Linguaggi dinamici – A.A. 2009/2010 14
  • 15.
    Polimorfismo „ È sufficienteridefinire un metodo all'interno di una sottoclasse per sostituirlo alle definizioni presenti nelle superclassi „ L'interprete Python gestisce il polimorfismo L interprete automaticamente, andandosi a cercare il metodo con la signature adatta „ All'interno di un metodo ridefinito nella sottoclasse, è possibile invocare il metodo tt l ibil i t d della superclasse con la seguente sintassi: BaseClassName.methodname(self, arguments) Linguaggi dinamici – A.A. 2009/2010 15
  • 16.
    ÆESEMPI Variabili private Private.py „ Ogni identificatore (variabile, metodo) __ident_ con almeno due underscore davanti ed al più un underscore dietro viene rinominato internamente in _c ass a e__ident, dove te a e te classname de t, do e classname è il nome della classe corrente senza gli underscore iniziali g Linguaggi dinamici – A.A. 2009/2010 16
  • 17.
    Vecchio e nuovostile della POO „ Nel vecchio stile: „ Le classi sono oggetti „ La ricerca di attributi avviene con un algoritmo statico (depth-first left-to-right) (depth-first, „ Nel nuovo stile: „ Le l L classi sono ti i i tipi „ La ricerca di attributi avviene in modo dinamico „ La gerarchia ha una radice: object „ Il nuovo stile gestisce meglio casi di eredità “a diamante”, in cui la stessa superclasse è raggiungibile tramite percorsi diversi Linguaggi dinamici – A.A. 2009/2010 17
  • 18.
    ÆESEMPI super Counter.py Counter2.py „ In Python non c’è il concetto di super „ Mancanza dovuta anche alla presenza di ereditarietà multipla „ Esiste però la funzione super(type object) che super(type, restituisce il “super tipo” della classe corrente „ Funziona solo con il nuovo stile di classi „ È necessario che all’apice della gerarchia ci sia object Linguaggi dinamici – A.A. 2009/2010 18
  • 19.
    ÆESEMPI Iteratori Reverse.py „ Il metodo __iter__ definisce un iteratore per la classe corrente „ Tale oggetto deve contenere un metodo next() „ Il metodo next definisce lo step di iterazione „ Seleziona un elemento diverso ad ogni invocazione „ Solleva una eccezione di tipo StopIteration quando tutti gli elementi sono stati selezionati Linguaggi dinamici – A.A. 2009/2010 19