Menu
Coddy logo textTech

연산자 오버로딩

Coddy Python 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 64개 중 34번째.

연산자 오버로딩을 사용하면 특수한 매직 메서드를 구현하여 클래스가 파이썬의 내장 연산자(+, -, *, 등)와 함께 작동하도록 할 수 있습니다.

다음은 연산자 오버로딩을 사용한 클래스의 예입니다:

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

__add__ 메서드는 + 연산자를 사용할 때 발생하는 동작을 정의합니다:

v1 = Vector(2, 3)
v2 = Vector(5, 7)
result = v1 + v2  # v1.__add__(v2)를 호출합니다
print(result)

__mul__ 메서드는 * 연산자를 사용할 때 어떤 일이 일어나는지 정의합니다:

v1 = Vector(2, 3)
scaled = v1 * 3   # v1.__mul__(3)을 호출합니다
print(scaled)

출력:

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

비교 연산자 추가하기:

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 - v1.__eq__(v2)를 호출합니다
print(v1 == v3)  # False

핵심 포인트: 연산자 오버로딩은 __add__ (+), __sub__ (-), __mul__ (*), __eq__ (==)와 같은 매직 메서드를 사용하여 객체에서 연산자가 작동하는 방식을 정의합니다. 이를 통해 클래스가 파이썬의 내장 연산자와 자연스럽게 동작하게 됩니다.

challenge icon

챌린지

중급

이 챌린지에서는 강력한 연산자 오버로딩을 사용하여 화폐 금액을 나타내는 Money 클래스를 구현합니다. 여러분의 구현은 포괄적인 테스트 스위트를 통해 철저히 테스트될 것입니다.

  • money.py - 이 파일은 여러분이 수정해야 할 유일한 파일입니다. 구현을 안내하는 TODO 주석이 포함된 클래스 정의가 들어 있습니다.
  • driver.py - 구현을 검증하는 광범위한 테스트 시나리오가 포함되어 있습니다 (수정하지 마세요).

다음 기능을 갖춘 Money 클래스를 구현하세요:

  1. amount (float)와 currency (string)를 인자로 받는 생성자
  2. 동일한 통화를 가진 Money 객체 간의 덧셈 (+)
  3. 금액을 배수로 늘리기 위한 숫자와의 곱셈 (*)
  4. Money 객체 간의 동등성 비교 (==)
  5. "X.XX CUR" 형식의 문자열 표현

치트 시트

연산자 오버로딩을 사용하면 특별한 매직 메서드를 구현하여 클래스가 파이썬의 내장 연산자와 함께 작동하도록 할 수 있습니다:

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

연산자 오버로딩을 위한 일반적인 매직 메서드:

  • + 연산자를 위한 __add__
  • - 연산자를 위한 __sub__
  • * 연산자를 위한 __mul__
  • == 연산자를 위한 __eq__
  • 문자열 표현을 위한 __str__

사용 예시:

v1 = Vector(2, 3)
v2 = Vector(5, 7)
result = v1 + v2  # v1.__add__(v2)를 호출합니다
scaled = v1 * 3   # v1.__mul__(3)를 호출합니다
print(v1 == v2)   # v1.__eq__(v2)를 호출합니다

직접 해보기

from money import Money

# 테스트 케이스 처리기
test_case = input()

def test_basic_functionality():
    # 초기화 및 문자열 표현 테스트
    m1 = Money(10.0, "USD")
    assert str(m1) == "10.00 USD", f"__str__ method failed, got {str(m1)}"
    
    # 덧셈 테스트
    m2 = Money(20.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "30.00 USD", f"Addition failed, got {str(m3)}"
    
    # 서로 다른 통화의 덧셈 테스트
    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)}"
    
    # 곱셈 테스트
    m6 = m1 * 3
    assert str(m6) == "30.00 USD", f"Multiplication failed, got {str(m6)}"
    
    # 동등성 테스트
    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():
    # 금액이 0인 경우 테스트
    m1 = Money(0.0, "USD")
    assert str(m1) == "0.00 USD", f"Zero amount string representation failed, got {str(m1)}"
    
    # 0과의 덧셈 테스트
    m2 = Money(10.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "10.00 USD", f"Addition with zero failed, got {str(m3)}"
    
    # 0과의 곱셈 테스트
    m4 = m2 * 0
    assert str(m4) == "0.00 USD", f"Multiplication by zero failed, got {str(m4)}"
    
    # 금액이 0일 때의 동등성 테스트
    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():
    # 음수 금액 테스트
    m1 = Money(-10.0, "USD")
    assert str(m1) == "-10.00 USD", f"Negative amount string representation failed, got {str(m1)}"
    
    # 음수 금액과의 덧셈 테스트
    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)}"
    
    # 음수 스칼라와의 곱셈 테스트
    m6 = m2 * -2
    assert str(m6) == "-40.00 USD", f"Multiplication by negative scalar failed, got {str(m6)}"
    
    # 음수 금액의 동등성 테스트
    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():
    # 매우 큰 금액 테스트
    m1 = Money(1000000.0, "USD")
    assert str(m1) == "1000000.00 USD", f"Large amount string representation failed, got {str(m1)}"
    
    # 큰 금액과의 덧셈 테스트
    m2 = Money(2000000.0, "USD")
    m3 = m1 + m2
    assert str(m3) == "3000000.00 USD", f"Addition with large amounts failed, got {str(m3)}"
    
    # 큰 스칼라와의 곱셈 테스트
    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():
    # 소수점 금액 테스트
    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)}"
    
    # 소수점 금액과의 덧셈 테스트
    m3 = Money(0.75, "USD")
    m4 = m1 + m3
    assert str(m4) == "11.00 USD", f"Addition with fractional amounts failed, got {str(m4)}"
    
    # 소수점 스칼라와의 곱셈 테스트
    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:
        # 이 연산들은 오류 없이 작동해야 함
        m1 = Money(10.0, "USD")
        m2 = m1 * 2
        m3 = m1 * 2.5
        
        # 다른 타입과의 동등성 테스트
        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():
    # 통화 대소문자 구분 테스트
    m1 = Money(10.0, "USD")
    m2 = Money(10.0, "usd")
    
    # 통화는 대소문자를 구분해야 함
    assert m1 != m2, "Currency comparison should be case-sensitive"
    
    # 대소문자가 다른 통화의 합산은 실패해야 함
    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():
    # 많은 Money 객체를 생성하고 연산 수행
    base = Money(1.0, "USD")
    result = base
    
    # 1000번의 덧셈 수행
    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)}"
    
    # 10번의 곱셈 수행
    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!")

# 입력에 따라 적절한 테스트 실행
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 icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

Object Oriented Programming의 모든 레슨