Compare commits

..
3 Commits
Author SHA1 Message Date
davide ed29b5907c aggiunge esercizio 42 2026-04-13 15:59:41 +02:00
davide e420bae5d5 aggiunge esercizio 41 2026-04-13 15:56:49 +02:00
davide 1200160f1c aggiunge esercizio 40 2026-04-13 15:47:19 +02:00
3 changed files with 16 additions and 79 deletions
+6 -30
View File
@@ -1,60 +1,36 @@
# 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): class WeekDayError(Exception):
pass pass
class Weeker: 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'] __GIORNI = ['lun', 'mar', 'mer', 'gio', 'ven', 'sab', 'dom']
def __init__(self, day): def __init__(self, day):
# Il costruttore riceve il nome del giorno (stringa).
# Controlliamo subito se il valore è valido.
if day not in Weeker.__GIORNI: if day not in Weeker.__GIORNI:
# Se il giorno non è nella lista, solleviamo la nostra eccezione.
raise WeekDayError("Giorno non valido: " + day) 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) self.__day_index = Weeker.__GIORNI.index(day)
def __str__(self): 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() return Weeker.__GIORNI[self.__day_index].capitalize()
def add_days(self, n): 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 self.__day_index = (self.__day_index + n) % 7
def subtract_days(self, n): 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 self.__day_index = (self.__day_index - n) % 7
# --- TEST --- # --- TEST ---
try: try:
weekday = Weeker('lun') weekday = Weeker('lun')
print(weekday) # → Lun print(weekday)
weekday.add_days(15) # 15 giorni dopo lunedì: 15 % 7 = 1 → martedì weekday.add_days(15)
print(weekday) # → Mar print(weekday)
weekday.subtract_days(23) # 23 giorni prima di martedì: (1 - 23) % 7 = 0 → domenica... weekday.subtract_days(23)
# aspetta: (1-23)=-22, -22%7=6 → dom. Ma la consegna mostra "Sole"? print(weekday)
# La consegna usa nomi diversi: adattiamo se necessario.
print(weekday) # → Dom
weekday = Weeker('lunedì') # Valore non valido → solleva WeekDayError weekday = Weeker('lunedì')
except WeekDayError: except WeekDayError:
print("Mi dispiace, non posso soddisfare la sua richiesta.") print("Mi dispiace, non posso soddisfare la sua richiesta.")
+7 -24
View File
@@ -1,45 +1,28 @@
# LAB-41: Classe Point (Punto) import math
# 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: class Point:
def __init__(self, x=0.0, y=0.0): def __init__(self, x, y):
# I parametri hanno valori di default (0.0), quindi si può creare self.__x = float(x)
# 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) self.__y = float(y)
def getx(self): def getx(self):
# Getter: restituisce la coordinata x.
# Necessario perché __x è privato e non accessibile dall'esterno.
return self.__x return self.__x
def gety(self): def gety(self):
# Getter: restituisce la coordinata y.
return self.__y return self.__y
def distance_from_xy(self, x, 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) return math.hypot(self.__x - x, self.__y - y)
def distance_from_point(self, point): 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()) return self.distance_from_xy(point.getx(), point.gety())
# --- TEST --- # --- TEST ---
point1 = Point(0, 0) # origine point1 = Point(0, 0)
point2 = Point(1, 1) # punto a distanza √2 dall'origine point2 = Point(1, 1)
# Distanza da point1 a point2: √((1-0)² + (1-0)²) = √2 ≈ 1.4142... print(point1.distance_from_point(point2))
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))
print(point2.distance_from_xy(2, 0)) # → 1.4142135623730951
+3 -25
View File
@@ -1,15 +1,8 @@
# 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 import math
class Point: class Point:
"""Rappresenta un punto nel piano cartesiano con coordinate private."""
def __init__(self, x=0.0, y=0.0): def __init__(self, x, y):
self.__x = float(x) self.__x = float(x)
self.__y = float(y) self.__y = float(y)
@@ -20,38 +13,23 @@ class Point:
return self.__y return self.__y
def distance_from_xy(self, x, y): def distance_from_xy(self, x, y):
# Distanza euclidea verso le coordinate (x, y)
return math.hypot(self.__x - x, self.__y - y) return math.hypot(self.__x - x, self.__y - y)
def distance_from_point(self, point): def distance_from_point(self, point):
# Distanza verso un altro oggetto Point
return self.distance_from_xy(point.getx(), point.gety()) return self.distance_from_xy(point.getx(), point.gety())
class Triangle: class Triangle:
"""Rappresenta un triangolo definito da tre vertici (oggetti Point)."""
def __init__(self, vertice1, vertice2, vertice3): 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] self.__vertici = [vertice1, vertice2, vertice3]
def perimeter(self): def perimeter(self):
# Il perimetro è la somma delle lunghezze dei tre lati. v = self.__vertici
# 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]) lato1 = v[0].distance_from_point(v[1])
lato2 = v[1].distance_from_point(v[2]) lato2 = v[1].distance_from_point(v[2])
lato3 = v[2].distance_from_point(v[0]) lato3 = v[2].distance_from_point(v[0])
return lato1 + lato2 + lato3 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)) triangle = Triangle(Point(0, 0), Point(1, 0), Point(0, 1))
print(triangle.perimeter()) # → 3.414213562373095 print(triangle.perimeter())