Menu
Coddy logo textTech

Sovraccarico degli operatori

Fa parte della sezione Programmazione orientata agli oggetti del percorso Python di Coddy. Lezione 34 di 64.

L'overloading degli operatori consente alle tue classi di funzionare con gli operatori integrati di Python (+, -, *, ecc.) implementando metodi magici speciali.

Ecco un esempio di classe con sovraccarico degli operatori:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)
    
    def __str__(self):
        return f"Vector({self.x}, {self.y})"

Il metodo __add__ definisce cosa succede quando usi l’operatore +:

v1 = Vector(2, 3)
v2 = Vector(5, 7)
result = v1 + v2  # Chiama v1.__add__(v2)
print(result)

Il metodo __mul__ definisce cosa succede quando usi l’operatore *:

v1 = Vector(2, 3)
scaled = v1 * 3   # Chiama v1.__mul__(3)
print(scaled)

Output:

Vector(7, 10)
Vector(6, 9)

Aggiungi operatori di confronto:

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __str__(self):
        return f"Vector({self.x}, {self.y})"

v1 = Vector(2, 3)
v2 = Vector(2, 3)
v3 = Vector(1, 1)

print(v1 == v2)  # True - llama a v1.__eq__(v2)
print(v1 == v3)  # False

Punto chiave: l'overloading degli operatori usa metodi magici come __add__ (+), __sub__ (-), __mul__ (*), __eq__ (==) per definire il funzionamento degli operatori con i tuoi oggetti. Questo fa sì che le tue classi si comportino in modo naturale con gli operatori integrati di Python.

challenge icon

Sfida

Medio

In questa sfida implementerai una classe Money che rappresenta importi monetari con un robusto overload degli operatori. La tua implementazione verrà verificata a fondo con una suite di test completa.

  • money.py - Questo è l’unico file da modificare. Contiene la definizione della classe con commenti TODO che guidano la tua implementazione.
  • driver.py - Contiene scenari di test approfonditi che convalidano la tua implementazione (non modificare).

Implementa la classe Money con le seguenti funzionalità:

  1. Un costruttore che accetta amount (float) e currency (stringa)
  2. Addizione (+) di oggetti Money con la stessa valuta
  3. Moltiplicazione (*) per un numero per scalare l’importo
  4. Confronto di uguaglianza (==) tra oggetti Money
  5. Rappresentazione come stringa nel formato “X.XX CUR”

Provalo tu

from money import Money

# Gestore dei casi di test
test_case = input()

def test_basic_functionality():
    # Verifica l'inizializzazione e la rappresentazione come stringa
    m1 = Money(10.0, "USD")
    assert str(m1) == "10.00 USD", f"__str__ method failed, got {str(m1)}"
    
    # Verifica l'addizione
    m2 = Money(20.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "30.00 USD", f"Addition failed, got {str(m3)}"
    
    # Verifica l'addizione di valute diverse
    m4 = Money(20.0, "EUR")
    try:
        m5 = m1 + m4
        assert False, "Adding different currencies should raise an error"
    except ValueError as e:
        assert str(e) == "Cannot add different currencies", f"Wrong error message: {str(e)}"
    
    # Verifica la moltiplicazione
    m6 = m1 * 3
    assert str(m6) == "30.00 USD", f"Multiplication failed, got {str(m6)}"
    
    # Verifica l'uguaglianza
    assert m1 == Money(10.0, "USD"), "Equality test failed"
    assert m1 != m2, "Inequality test failed"
    
    print("All basic functionality tests passed!")

def test_zero_values():
    # Verifica il comportamento con un importo pari a zero
    m1 = Money(0.0, "USD")
    assert str(m1) == "0.00 USD", f"Zero amount string representation failed, got {str(m1)}"
    
    # Verifica l'addizione con zero
    m2 = Money(10.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "10.00 USD", f"Addition with zero failed, got {str(m3)}"
    
    # Verifica la moltiplicazione per zero
    m4 = m2 * 0
    assert str(m4) == "0.00 USD", f"Multiplication by zero failed, got {str(m4)}"
    
    # Verifica l'uguaglianza con un importo pari a zero
    assert m1 == Money(0.0, "USD"), "Equality with zero amount failed"
    assert m1 != m2, "Inequality with zero amount failed"
    
    print("All zero value tests passed!")

def test_negative_values():
    # Verifica il comportamento con un importo negativo
    m1 = Money(-10.0, "USD")
    assert str(m1) == "-10.00 USD", f"Negative amount string representation failed, got {str(m1)}"
    
    # Verifica l'addizione con importi negativi
    m2 = Money(20.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "10.00 USD", f"Addition with negative amount failed, got {str(m3)}"
    
    m4 = Money(-5.0, "USD")
    m5 = m1 + m4
    assert str(m5) == "-15.00 USD", f"Addition of two negative amounts failed, got {str(m5)}"
    
    # Verifica la moltiplicazione per uno scalare negativo
    m6 = m2 * -2
    assert str(m6) == "-40.00 USD", f"Multiplication by negative scalar failed, got {str(m6)}"
    
    # Verifica l'uguaglianza con importi negativi
    assert m1 == Money(-10.0, "USD"), "Equality with negative amount failed"
    assert m1 != m2, "Inequality with negative amount failed"
    
    print("All negative value tests passed!")

def test_large_values():
    # Verifica il comportamento con importi molto elevati
    m1 = Money(1000000.0, "USD")
    assert str(m1) == "1000000.00 USD", f"Large amount string representation failed, got {str(m1)}"
    
    # Verifica l'addizione con importi elevati
    m2 = Money(2000000.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "3000000.00 USD", f"Addition with large amounts failed, got {str(m3)}"
    
    # Verifica la moltiplicazione per uno scalare elevato
    m4 = m1 * 1000
    assert str(m4) == "1000000000.00 USD", f"Multiplication with large scalar failed, got {str(m4)}"
    
    print("All large value tests passed!")

def test_precision():
    # Verifica il comportamento con importi frazionari
    m1 = Money(10.25, "USD")
    assert str(m1) == "10.25 USD", f"Fractional amount string representation failed, got {str(m1)}"
    
    m2 = Money(10.2, "USD")
    assert str(m2) == "10.20 USD", f"Two decimal place formatting failed, got {str(m2)}"
    
    # Verifica l'addizione con importi frazionari
    m3 = Money(0.75, "USD")
    m4 = m1 + m3
    assert str(m4) == "11.00 USD", f"Addition with fractional amounts failed, got {str(m4)}"
    
    # Verifica la moltiplicazione per uno scalare frazionario
    m5 = m1 * 0.5
    assert str(m5) == "5.13 USD", f"Multiplication with fractional scalar failed, got {str(m5)}"
    
    print("All precision tests passed!")

def test_type_validation():
    try:
        # Queste operazioni dovrebbero funzionare senza errori
        m1 = Money(10.0, "USD")
        m2 = m1 * 2
        m3 = m1 * 2.5
        
        # Verifica l'uguaglianza con tipi diversi
        assert (m1 == "10.00 USD") == False, "Equality with string should return False"
        assert (m1 == 10.0) == False, "Equality with number should return False"
        
        print("All type validation tests passed!")
    except Exception as e:
        print(f"Type validation test failed: {e}")

def test_currency_case_sensitivity():
    # Verifica la distinzione tra maiuscole e minuscole nei codici delle valute
    m1 = Money(10.0, "USD")
    m2 = Money(10.0, "usd")
    
    # I codici delle valute dovrebbero distinguere tra maiuscole e minuscole
    assert m1 != m2, "Currency comparison should be case-sensitive"
    
    # L'aggiunta di valute con maiuscole e minuscole diverse deve fallire
    try:
        m3 = m1 + m2
        assert False, "Adding different currency cases should raise an error"
    except ValueError as e:
        assert str(e) == "Cannot add different currencies", f"Wrong error message: {str(e)}"
    
    print("All currency case sensitivity tests passed!")

def test_performance():
    # Crea molti oggetti Money ed esegui operazioni
    base = Money(1.0, "USD")
    result = base
    
    # Esegui 1000 addizioni
    for i in range(1000):
        result = result + Money(1.0, "USD")
    
    assert str(result) == "1001.00 USD", f"Performance test addition failed, got {str(result)}"
    
    # Esegui 10 moltiplicazioni
    result = base
    for i in range(10):
        result = result * 2
    
    assert str(result) == "1024.00 USD", f"Performance test multiplication failed, got {str(result)}"
    
    print("All performance tests passed!")

# Esegui il test appropriato in base all'input
if test_case == "basic_test":
    test_basic_functionality()
elif test_case == "zero_values":
    test_zero_values()
elif test_case == "negative_values":
    test_negative_values()
elif test_case == "large_values":
    test_large_values()
elif test_case == "precision":
    test_precision()
elif test_case == "type_validation":
    test_type_validation()
elif test_case == "currency_case":
    test_currency_case_sensitivity()
elif test_case == "performance":
    test_performance()
else:
    print(f"Unknown test case: {test_case}")
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Python online