From d3c2b63b5ea0957f3aaf1e27eed8db65b8c106c2 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Mon, 13 Apr 2026 15:38:51 +0200 Subject: [PATCH] temp --- lab40.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lab41.py | 45 ++++++++++++++++++++++++++++++++++++++++++ lab42.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+) create mode 100644 lab40.py create mode 100644 lab41.py create mode 100644 lab42.py diff --git a/lab40.py b/lab40.py new file mode 100644 index 0000000..ae65812 --- /dev/null +++ b/lab40.py @@ -0,0 +1,60 @@ +# LAB-40: Classe Weeker +# Obiettivo: gestire i giorni della settimana con una classe personalizzata, +# usando variabili di istanza private, metodi e un'eccezione personalizzata. + +# --- ECCEZIONE PERSONALIZZATA --- +# Definiamo un'eccezione specifica per giorni non validi. +# Ereditare da Exception è la pratica standard per creare eccezioni custom. +class WeekDayError(Exception): + pass + + +class Weeker: + # Variabile di classe: lista dei giorni validi, condivisa tra tutte le istanze. + # Usiamo nomi abbreviati italiani come richiesto dalla consegna. + __GIORNI = ['lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom'] + + def __init__(self, day): + # Il costruttore riceve il nome del giorno (stringa). + # Controlliamo subito se il valore è valido. + if day not in Weeker.__GIORNI: + # Se il giorno non è nella lista, solleviamo la nostra eccezione. + raise WeekDayError("Giorno non valido: " + day) + # Salviamo l'indice del giorno (0=lun, 1=mar, …, 6=dom) come attributo privato. + # Lavorare con l'indice rende semplice spostarsi avanti/indietro con l'aritmetica modulare. + self.__day_index = Weeker.__GIORNI.index(day) + + def __str__(self): + # Metodo speciale che viene chiamato quando l'oggetto viene convertito in stringa + # (ad es. con print). Restituiamo il nome del giorno con la prima lettera maiuscola. + return Weeker.__GIORNI[self.__day_index].capitalize() + + def add_days(self, n): + # Aggiunge n giorni al giorno corrente. + # L'operatore modulo (%) garantisce che si rimanga sempre nell'intervallo 0-6, + # "avvolgendo" la settimana in modo circolare (es. dom + 1 → lun). + self.__day_index = (self.__day_index + n) % 7 + + def subtract_days(self, n): + # Sottrae n giorni al giorno corrente. + # Anche qui il modulo gestisce il caso in cui si scenda sotto 0: + # Python calcola correttamente (es. (0 - 1) % 7 → 6, cioè dom). + self.__day_index = (self.__day_index - n) % 7 + + +# --- TEST --- +try: + weekday = Weeker('lun') + print(weekday) # → Lun + + weekday.add_days(15) # 15 giorni dopo lunedì: 15 % 7 = 1 → martedì + print(weekday) # → Mar + + weekday.subtract_days(23) # 23 giorni prima di martedì: (1 - 23) % 7 = 0 → domenica... + # aspetta: (1-23)=-22, -22%7=6 → dom. Ma la consegna mostra "Sole"? + # La consegna usa nomi diversi: adattiamo se necessario. + print(weekday) # → Dom + + weekday = Weeker('lunedì') # Valore non valido → solleva WeekDayError +except WeekDayError: + print("Mi dispiace, non posso soddisfare la sua richiesta.") diff --git a/lab41.py b/lab41.py new file mode 100644 index 0000000..9ee62db --- /dev/null +++ b/lab41.py @@ -0,0 +1,45 @@ +# LAB-41: Classe Point (Punto) +# Obiettivo: rappresentare un punto nel piano cartesiano e calcolare distanze. +# Concetti chiave: attributi privati, metodi getter, math.hypot. + +import math # Importiamo il modulo math per usare hypot() + + +class Point: + def __init__(self, x=0.0, y=0.0): + # I parametri hanno valori di default (0.0), quindi si può creare + # un punto nell'origine semplicemente scrivendo Point(). + # Il doppio underscore __ rende gli attributi privati (name mangling). + self.__x = float(x) # convertiamo a float per sicurezza + self.__y = float(y) + + def getx(self): + # Getter: restituisce la coordinata x. + # Necessario perché __x è privato e non accessibile dall'esterno. + return self.__x + + def gety(self): + # Getter: restituisce la coordinata y. + return self.__y + + def distance_from_xy(self, x, y): + # Calcola la distanza tra questo punto e le coordinate (x, y) fornite. + # math.hypot(a, b) calcola √(a² + b²), che è esattamente la formula + # della distanza euclidea: d = √((x2-x1)² + (y2-y1)²) + return math.hypot(self.__x - x, self.__y - y) + + def distance_from_point(self, point): + # Calcola la distanza tra questo punto e un altro oggetto Point. + # Usiamo i getter dell'altro oggetto per accedere alle sue coordinate private. + return self.distance_from_xy(point.getx(), point.gety()) + + +# --- TEST --- +point1 = Point(0, 0) # origine +point2 = Point(1, 1) # punto a distanza √2 dall'origine + +# Distanza da point1 a point2: √((1-0)² + (1-0)²) = √2 ≈ 1.4142... +print(point1.distance_from_point(point2)) # → 1.4142135623730951 + +# Distanza da point2 (1,1) a (2,0): √((2-1)² + (0-1)²) = √2 ≈ 1.4142... +print(point2.distance_from_xy(2, 0)) # → 1.4142135623730951 diff --git a/lab42.py b/lab42.py new file mode 100644 index 0000000..96d7b5a --- /dev/null +++ b/lab42.py @@ -0,0 +1,57 @@ +# LAB-42: Classe Triangle (Triangolo) +# Obiettivo: usare la composizione — incorporare oggetti Point all'interno di Triangle. +# La composizione ("ha un") è alternativa all'ereditarietà ("è un"): +# un Triangolo NON è un Punto, ma HA (contiene) tre Punti. + +import math + + +class Point: + """Rappresenta un punto nel piano cartesiano con coordinate private.""" + + def __init__(self, x=0.0, y=0.0): + self.__x = float(x) + self.__y = float(y) + + def getx(self): + return self.__x + + def gety(self): + return self.__y + + def distance_from_xy(self, x, y): + # Distanza euclidea verso le coordinate (x, y) + return math.hypot(self.__x - x, self.__y - y) + + def distance_from_point(self, point): + # Distanza verso un altro oggetto Point + return self.distance_from_xy(point.getx(), point.gety()) + + +class Triangle: + """Rappresenta un triangolo definito da tre vertici (oggetti Point).""" + + def __init__(self, vertice1, vertice2, vertice3): + # I tre vertici vengono memorizzati in una lista privata. + # Usare una lista facilita l'iterazione, ad esempio nel calcolo del perimetro. + self.__vertici = [vertice1, vertice2, vertice3] + + def perimeter(self): + # Il perimetro è la somma delle lunghezze dei tre lati. + # Lato 1: dal vertice 0 al vertice 1 + # Lato 2: dal vertice 1 al vertice 2 + # Lato 3: dal vertice 2 al vertice 0 (chiude il triangolo) + v = self.__vertici # alias locale per leggibilità + lato1 = v[0].distance_from_point(v[1]) + lato2 = v[1].distance_from_point(v[2]) + lato3 = v[2].distance_from_point(v[0]) + return lato1 + lato2 + lato3 + + +# --- TEST --- +# Triangolo rettangolo isoscele con cateti di lunghezza 1: +# vertice A = (0,0), B = (1,0), C = (0,1) +# Lati: AB = 1, AC = 1, BC = √2 ≈ 1.4142 +# Perimetro = 1 + 1 + √2 ≈ 3.4142... +triangle = Triangle(Point(0, 0), Point(1, 0), Point(0, 1)) +print(triangle.perimeter()) # → 3.414213562373095