Menu
Coddy logo textTech

Sobrecarga de Operadores

Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 34 de 64.

A sobrecarga de operadores permite que suas classes trabalhem com os operadores integrados do Python (+, -, *, etc.) ao implementar métodos mágicos especiais.

Aqui está um exemplo de uma classe com sobrecarga de operadores:

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})"

O método __add__ define o que acontece quando você usa o operador +:

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

O método __mul__ define o que acontece quando você usa o operador *:

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

Saída:

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

Adicione operadores de comparação:

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 - chama v1.__eq__(v2)
print(v1 == v3)  # False

Ponto Chave: A sobrecarga de operadores usa métodos mágicos como __add__ (+), __sub__ (-), __mul__ (*), __eq__ (==) para definir como os operadores funcionam com seus objetos. Isso faz com que suas classes se comportem naturalmente com os operadores integrados do Python.

challenge icon

Desafio

Médio

Neste desafio, você implementará uma classe Money que representa quantias monetárias com sobrecarga de operadores robusta. Sua implementação será testada minuciosamente em relação a uma suíte de testes abrangente.

  • money.py - Este é o único arquivo que você precisa editar. Ele contém a definição da classe com comentários TODO orientando sua implementação.
  • driver.py - Contém cenários de teste extensivos que validam sua implementação (não modifique).

Implemente a classe Money com os seguintes recursos:

  1. Construtor que recebe amount (float) e currency (string)
  2. Adição (+) de objetos Money com a mesma moeda
  3. Multiplicação (*) por um número para escalar a quantia
  4. Comparação de igualdade (==) entre objetos Money
  5. Representação em string no formato “X.XX CUR”

Folha de consulta

A sobrecarga de operadores permite que as classes trabalhem com os operadores integrados do Python ao implementar métodos mágicos especiais:

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 __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __str__(self):
        return f"Vector({self.x}, {self.y})"

Métodos mágicos comuns para sobrecarga de operadores:

  • __add__ para o operador +
  • __sub__ para o operador -
  • __mul__ para o operador *
  • __eq__ para o operador ==
  • __str__ para representação de string

Exemplo de uso:

v1 = Vector(2, 3)
v2 = Vector(5, 7)
result = v1 + v2  # Chama v1.__add__(v2)
scaled = v1 * 3   # Chama v1.__mul__(3)
print(v1 == v2)   # Chama v1.__eq__(v2)

Experimente você mesmo

from money import Money

# Manipulador de caso de teste
test_case = input()

def test_basic_functionality():
    # Testa a inicialização e a representação em string
    m1 = Money(10.0, "USD")
    assert str(m1) == "10.00 USD", f"__str__ method failed, got {str(m1)}"
    
    # Testa a adição
    m2 = Money(20.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "30.00 USD", f"Addition failed, got {str(m3)}"
    
    # Testa a adição de moedas diferentes
    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)}"
    
    # Testa a multiplicação
    m6 = m1 * 3
    assert str(m6) == "30.00 USD", f"Multiplication failed, got {str(m6)}"
    
    # Testa a igualdade
    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():
    # Testa com valor zero
    m1 = Money(0.0, "USD")
    assert str(m1) == "0.00 USD", f"Zero amount string representation failed, got {str(m1)}"
    
    # Testa a adição com zero
    m2 = Money(10.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "10.00 USD", f"Addition with zero failed, got {str(m3)}"
    
    # Testa a multiplicação por zero
    m4 = m2 * 0
    assert str(m4) == "0.00 USD", f"Multiplication by zero failed, got {str(m4)}"
    
    # Testa a igualdade com valor 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():
    # Testa com valor negativo
    m1 = Money(-10.0, "USD")
    assert str(m1) == "-10.00 USD", f"Negative amount string representation failed, got {str(m1)}"
    
    # Testa a adição com valores negativos
    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)}"
    
    # Testa a multiplicação por escalar negativo
    m6 = m2 * -2
    assert str(m6) == "-40.00 USD", f"Multiplication by negative scalar failed, got {str(m6)}"
    
    # Testa a igualdade com valores negativos
    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():
    # Testa com valores muito grandes
    m1 = Money(1000000.0, "USD")
    assert str(m1) == "1000000.00 USD", f"Large amount string representation failed, got {str(m1)}"
    
    # Testa a adição com valores grandes
    m2 = Money(2000000.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "3000000.00 USD", f"Addition with large amounts failed, got {str(m3)}"
    
    # Testa a multiplicação com escalar grande
    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():
    # Testa com valores fracionários
    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)}"
    
    # Testa a adição com valores fracionários
    m3 = Money(0.75, "USD")
    m4 = m1 + m3
    assert str(m4) == "11.00 USD", f"Addition with fractional amounts failed, got {str(m4)}"
    
    # Testa a multiplicação com escalar fracionário
    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:
        # Estas operações devem funcionar sem erros
        m1 = Money(10.0, "USD")
        m2 = m1 * 2
        m3 = m1 * 2.5
        
        # Testa a igualdade com tipos diferentes
        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():
    # Testa a sensibilidade a maiúsculas/minúsculas da moeda
    m1 = Money(10.0, "USD")
    m2 = Money(10.0, "usd")
    
    # Moedas devem ser sensíveis a maiúsculas/minúsculas
    assert m1 != m2, "Currency comparison should be case-sensitive"
    
    # Adicionar casos diferentes deve falhar
    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():
    # Cria muitos objetos Money e realiza operações
    base = Money(1.0, "USD")
    result = base
    
    # Realiza 1000 adições
    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)}"
    
    # Realiza 10 multiplicações
    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!")

# Executa o teste apropriado com base na entrada
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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Object Oriented Programming