Il 0% ha trovato utile questo documento (0 voti)
1 visualizzazioni26 pagine

Classi

Il documento tratta della definizione e utilizzo delle classi in Python, evidenziando la creazione di nuovi tipi di dati e l'importanza della programmazione orientata agli oggetti. Viene presentato un esempio pratico di una classe 'Student' con metodi per gestire le proprietà e i voti, insieme a un esempio di classe 'Rectangle' per modellare forme geometriche. Infine, si discute la differenza tra metodi e funzioni, la mutabilità degli oggetti e il problema dell'aliasing.

Caricato da

Leon Bacci
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Il 0% ha trovato utile questo documento (0 voti)
1 visualizzazioni26 pagine

Classi

Il documento tratta della definizione e utilizzo delle classi in Python, evidenziando la creazione di nuovi tipi di dati e l'importanza della programmazione orientata agli oggetti. Viene presentato un esempio pratico di una classe 'Student' con metodi per gestire le proprietà e i voti, insieme a un esempio di classe 'Rectangle' per modellare forme geometriche. Infine, si discute la differenza tra metodi e funzioni, la mutabilità degli oggetti e il problema dell'aliasing.

Caricato da

Leon Bacci
Copyright
© © All Rights Reserved
Per noi i diritti sui contenuti sono una cosa seria. Se sospetti che questo contenuto sia tuo, rivendicalo qui.
Formati disponibili
Scarica in formato PDF, TXT o leggi online su Scribd
Sei sulla pagina 1/ 26

Classi

Tipi
• Un tipo di dato (data type) definisce per una variabile che tipo di informazioni posso
rappresentarvi e che operazioni sono possibili e con che risultato.

• Abbiamo visto tipi scalari: int, float, bool

• e tipi strutturati: str, list, dict, set, tuple

In entrambi i casi vi sono operazioni che si possono effettuare (+,-) e nel caso di tipi con struttura
interna anche i metodi che si possono chiamare ( l.append(), etc etc)
Definire nuovi tipi
• Vorremmo quindi creare dei nuvoi tipi di dati

• Nella definizione di un nuovo tipo dobbiamo stabilire:


• Quali informazioni deve contenere (proprietà o attributi)
• Quali operazioni possiamo effettuarvi (metodi)
Classi
• Python usa il concetto di classe per la definizione di nuovi tipi di dati

• E’ un concetto molto comune nella cosiddetta programmazione orientata agli oggetti

• In questo corso useremo le classi per definire dei semplici tipi senza addentrarci nei dettagli della
programmazione a oggetti
Classi class Student:
def __init__(self, name, lastname, id_number):
self.name = name
• Modelliamo uno studente per un self.lastname = lastname
sistema di gestione della carriera self.id_number = id_number
• Usiamo la parola chiave class self.grades = []

def get_average_grade(self):
• Funziona simile alla definizione di if len(self.grades)>0:
una funzione return sum(self.grades)/len(self.grades)
else:
class NomeClasse: return 0
indentazione def add_grade(self, grade):
if 18 <= grade <= 30:
self.grades.append(grade)
else:
print( "vote in the wrong range")
Classi class Student:
def __init__(self, name, lastname, id_number):
self.name = name
• Modelliamo uno studente per un self.lastname = lastname
sistema di gestione della carriera self.id_number = id_number
self.grades = []

• Ogni metodo è una funzione def get_average_grade(self):


definita con la sintassi usuale ma if len(self.grades)>0:
all’interno dello scope della return sum(self.grades)/len(self.grades)
classe else:
return 0
def add_grade(self, grade):
• I metodi delle classi hanno if 18 <= grade <= 30:
sempre un parametro formale self self.grades.append(grade)
che consente il riferimento agli else:
attributi interni dell’oggetto print( "vote in the wrong range")
Classi class Student:
def __init__(self, name, lastname, id_number):
self.name = name
• Modelliamo uno studente per un self.lastname = lastname
sistema di gestione della carriera self.id_number = id_number
self.grades = []

• Ogni metodo è una funzione def get_average_grade(self):


definita con la sintassi usuale ma if len(self.grades)>0:
all’interno dello scope della return sum(self.grades)/len(self.grades)
classe else:
return 0
def add_grade(self, grade):
• I metodi delle classi hanno if 18 <= grade <= 30:
sempre un parametro formale self self.grades.append(grade)
che consente il riferimento agli else:
attributi interni dell’oggetto print( "vote in the wrong range")
Classi class Student:
def __init__(self, name, lastname, id_number):
self.name = name
• Modelliamo uno studente per un self.lastname = lastname
sistema di gestione della carriera self.id_number = id_number
self.grades = []

• Vi sono alcuni metodi ‘speciali’ def get_average_grade(self):


per ora vediamo il fondamentale if len(self.grades)>0:
__init__ che definisce il return sum(self.grades)/len(self.grades)
costruttore else:
return 0
def add_grade(self, grade):
• Usiamo __init__ per creare le if 18 <= grade <= 30:
variabili attributo dell’oggetto self.grades.append(grade)
inizializzarle. else:
• E’ possibile passare parametri al print( "vote in the wrong range")
costruttore __init__
Classi
• Modelliamo uno studente per un >>>students = []
sistema di gestione della carriera >>> n = input('nome: ')
>>> ln = input('cognome: ')
>>> m = input('matricola: ‘)
• E adesso? come lo usiamo?
>>> s = Student(n,ln,m)
>>> students.append(s)
• Abbiamo un oggetto s strutturato
internamente che tramite un #possiamo modificare le proprietà direttamente
singolo nome mi consente di >>> s.matricola = 3
manipolare un insieme di variabili
#possiamo aggiungere un voto

• Si può accedere alle proprietà con >>> s.grades.append(25)


il .
Classi
• Modelliamo uno studente per un >>>students = []
sistema di gestione della carriera >>> n = input('nome: ')
>>> ln = input('cognome: ')
>>> m = input('matricola: ‘)
• E adesso? come lo usiamo?
>>> s = Student(n,ln,m)
>>> students.append(s)
• Possiamo creare degli oggetti di
tipo Student usando il costruttore #possiamo modificare le proprietà direttamente
>>> s.matricola = 3

• scrivendo NomeClasse(parametri) #possiamo aggiungere un voto


invochiamo la funzione __init__
che allocherà la memoria per un >>> s.grades.append(25)
nuovo oggetto e lo restituirà
Classi
• Modelliamo uno studente per un >>>students = []
sistema di gestione della carriera >>> n = input('nome: ')
>>> ln = input('cognome: ')
>>> m = input('matricola: ‘)
• E adesso? come lo usiamo?
>>> s = Student(n,ln,m)
>>> students.append(s)
• Si può accedere alle proprietà con
il . #possiamo modificare le proprietà direttamente
>>> s.id_number = 3

• Se il campo a cui accediamo #possiamo aggiungere un voto


dell’oggetto è a sua volta un
oggetto con dei campi/metodi >>> s.grades.append(25)
possiamo accedervi con la stessa
sintassi
Classi
• Modelliamo uno studente per un >>>students = []
sistema di gestione della carriera >>> n = input('nome: ')
>>> ln = input('cognome: ')
>>> m = input('matricola: ‘)
• Potremmo usare un metodo per
modificare la lista di voti in modo >>> s = Student(n,ln,m)
da controllare i valori inseriti >>> students.append(s)

#possiamo modificare le proprietà direttamente


• Questo consente di controllare >>> s. id_number = 3
l’input al mio oggetto
mantenendolo in uno stato #possiamo aggiungere un voto
corretto.
>>> s.grades.append(25)

>>> s.add_grade(12)
vote in the wrong range
Classi
• Un altro esempio… class Rectangle:
def __init__(self, x,y, height, width):
self.x = x
• Modelliamo un rettangolo, ci self.y = y
bastano 4 numeri… self.width = width
self.height = height

• x,y def area(self):


• larghezza e altezza return self.width*self.height

• Questo è un rettangolo allineato


agli assi dove x e y sono il vertice
in basso a sinistra
Classi
• Un oggetto può avere riferimenti class Point:
anche ad altri oggetti. def __init__(self, x,y):
self.x = x
self.y = y
• Ad esempio è comodo pensare a
x,y come ad un punto class Rectangle:
def __init__(self, p, height, width):
self.p = p
• Introduciamo la classe Point self.width = width
self.height = height

def area(self):
return self.width*self.height
Classi e funzioni
• Posso definire funzioni al di fuori delle classi a cui passo oggetti

• Ricordando il concetto di duck typing basta che tratto gli argomenti ’come si
aspettano’

• Definiamo una funzione per controllare se un punto è dentro un rettangolo.


def inside (r, p):
return r.p.x <= p.x <= r.p.x+r.width and r.p.y <= p.y <= r.p.y+r.height
Classi e funzioni A1 B1

• Possiamo riusare una funzione come questa per valutare se un A2 B2


rettangolo si interseca con un altro
• Basterà verificare che almeno un vertice di un rettangolo sia dentro C1 D1
l’altro…
• Aiutiamoci con una funzione che restituisce una lista di Point coi vertici

def vertices(self): C2 D2
'’’
Returns
-------
list with all the vertices
'''
return [self.p, Point(self.p.x+self.width, self.p.y),\
Point(self.p.x+self.width,self.p.y+self.height), \
Point(self.p.x, self.p.y+self.height)]
Classi e funzioni A1 B1

• Possiamo riusare una funzione come questa per valutare se un A2 B2


rettangolo si interseca con un altro
• A questo punto facciamo due cicli per testare le due condizioni C1 D1

def intersect(r1, r2):


result = False
C2 D2
for v in r1.vertices():
if inside(r2,v):
result=True
return result
Classi e funzioni A1 B1

• Le funzioni possono anche restituire oggetti A2 B2

• Supponiamo di voler calcolare il rettangolo intersezione (se esiste) C1 D1

def intersection(r1, r2):


x = max(r1.p.x, r2.p.x)
C2 D2
y = max(r1.p.y, r2.p.y)
w = min(r1.p.x+r1.width, r2.p.x+r2.width) - max(r1.p.x, r2.p.x)
h = min(r1.p.y + r1.height, r2.p.y + r2.height) - max(r1.p.y, r2.p.y)
if w>0 and h>0:
return Rectangle(Point(x,y), w, h)
else:
return None
Classi e funzioni A1 B1

• A questo punto potremmo riscrivere il test di intersezione testando se il A2 B2


rettangolo intersezione esiste

C1 D1

def intersect(r1, r2):


if intersection(r1, r2) != None:
C2 D2
return True
else:
return False
Metodi o Funzioni?

• In alcuni linguaggi il paradigma a oggetti è forzato sul programmatore in maniera pesante (Java)

• in Java NON si possono definire funzioni che non siano metodi!!!

• In python si possono scrivere programmi senza classi, e addirittura programmi senza funzioni!!!

• Come strutturiamo il codice? come si decide se scrivere una funzione esterna o un metodo della
classe?
Metodi o Funzioni?

• Come strutturiamo il codice? come si decide se scrivere una funzione esterna o un metodo della
classe?

• In generale se una funzione ha esclusivamente a che fare con gli attributi dell’oggetto stesso, magari
per modificarli o per calcolare dei nuovi valori da essi.
class Student:

def get_average_grade(self):
if len(self.grades)>0:
return sum(self.grades)/len(self.grades)
else:
return 0
Metodi o Funzioni?

• Come strutturiamo il codice? come si decide se scrivere una funzione esterna o un metodo della
classe?

• In generale se una funzione ha esclusivamente a che fare con gli attributi dell’oggetto stesso, magari
per modificarli o per calcolare dei nuovi valori da essi.
def get_average_grade(s):
if len(s.grades)>0:
return sum(s.grades)/len(s.grades)
else:
return 0
Metodi o Funzioni?

• Se una funzione mette in relazione due o più oggetti ‘alla pari’ ha senso che la funzione risieda
esternamente all’oggetto

def inside (r, p):


return r.p.x <= p.x <= r.p.x+r.width and r.p.y <= p.y <= r.p.y+r.height

• Non sarebbe sbagliatissimo definirla come metodo ma sarebbe da chiedersi se metterla nel Point o
nel Rectangle!

• Un altro criterio di design è il seguente: se condivido questa classe con qualcuno senza le funzioni
che la usano la sto privando di funzionalità fondamentali?
• In quel caso potrebbe avere senso definire le funzioni che sono più connesse alla natura della classe.
Oggetti in Memoria
• Vengono creati due rettangoli r1 e r2 che sono poi passati alla
funzione intersection

• Ogni rettangolo ha un riferimento ad un punto

• Quando viene chiamata intersection al termine viene creato un


nuovo rettangolo che verrà poi restituito a intersect
Oggetti Mutabilità e Aliasing
• Gli oggetti sono mutabili e come già visto per liste e dizionari
danno origine al problema dell’aliasing
• Se assegno r1 a r2 le modifiche a r2 si applicano anche a r1
Oggetti Mutabilità e Aliasing
• Gli oggetti sono mutabili e come già visto per liste e dizionari
danno origine al problema dell’aliasing
• Se assegno r1 a r2 le modifiche a r2 si applicano anche a r1

Potrebbero piacerti anche