인공지능을 좋아하는 곧미남

[python] 다형성이란 뭘까? 본문

code_study/python world

[python] 다형성이란 뭘까?

곧미남 2024. 12. 26. 17:02
728x90

오늘은 다형성에 대해서 알아보고 python의 method overriding 기법을 활용해 다형성에 대한 예시 코드를 구현하고 설명해보겠습니다.


다형성이란? 서로 다른 클래스에 선언된 같은 이름의 함수가 다른 동작을 하는 것입니다.

직관적인 예로 키보드를 누르는 동일한 행위에 대해 ESC, CTRL, SHIFT와 같은 실제 키가 다른 동작을 하는 것을 의미합니다.

 

Method Override가 다형성의 한 예입니다.

# 같은 이름의 함수가 다른 동작을 하게 만들기.

class Student_1:
    
    def __init__(self, money):
        
        self.money = money
        
    def payback(self):
        
        return self.money * 20

class Student_2:
    
    def __init__(self, money):
        
        self.money = money
        
    def payback(self):
        
        return self.money * 2

person1 = Student_1(10)
person2 = Student_2(10)

print(f"person1 payback: {person1.payback()}")
print(f"person2 payback: {person2.payback()}")

출력 결과:

person1 payback: 200

person2 payback: 20

이 처럼 Method Override를 활용해 다형성을 성립하는 코드를 구현했습니다. 서로 다른 클래스에 존재하는 동일한 이름의 payback()함수의 결과는 다르게 작동합니다.

 

이런 다형성에 대한 개념을 실제 어떤 문제를 코드로 구현할때 사용할지 생각해보았습니다.

 

저는 다양한 결제 방법을 처리하는 결제 시스템에 이 다형성을 활용해서 각기 다른 지불 방법에 대해서 지불된 결과를 알려주는 print문을 각기 다른 안내문으로 사용할 수 있다고 생각이 들어 이렇게 구현해보았습니다.

class PaymentMethod:
    def pay(self, amount):
        raise NotImplementedError("Subclasses must implement this method")

class CardPayment(PaymentMethod):
    def pay(self, amount):
        print(f"Paid {amount} using Card.")

class CashPayment(PaymentMethod):
    def pay(self, amount):
        print(f"Paid {amount} in Cash.")

def process_payment(payment_method, amount):
    payment_method.pay(amount)

# 다형성 사용
card = CardPayment()
cash = CashPayment()

process_payment(card, 100)  # Paid 100 using Card.
process_payment(cash, 50)  # Paid 50 in Cash.

출력 결과:

Paid 100 using Card.

Paid 50 in Cash.

 

각기 다른 결제 방법에 대한 지불 결과 알림 메세지를 출력하는 함수를 pay함수로 동일하게 선언하고 출력을 다르게 사용할 수 있었습니다.

 

이처럼 다형성을 활용해서 현실적인 문제를 보다 효율적으로 구현할 수 있습니다.


다형성을 활용한 예시!

 

1. 코드의 확장성과 유지보수성 향상

  • 새로운 기능을 추가할 때 기존 코드를 수정할 필요 없이 클래스를 확장하면 됩니다.
  • 예: 새로운 학생 클래스(Student_3)를 추가하더라도 기존 코드는 그대로 유지할 수 있습니다.

코드 예시: 학생의 다형성

class Student:
    def payback(self):
        raise NotImplementedError("Subclasses must implement this method")

class Student1(Student):
    def __init__(self, money):
        self.money = money

    def payback(self):
        return self.money * 20

class Student2(Student):
    def __init__(self, money):
        self.money = money

    def payback(self):
        return self.money * 2

class Student3(Student):
    def __init__(self, money):
        self.money = money

    def payback(self):
        return self.money * 10

# 사용하는 코드
def calculate_payback(student):
    return student.payback()

students = [Student1(10), Student2(10), Student3(10)]

for student in students:
    print(f"{student.__class__.__name__} payback: {calculate_payback(student)}")

 

2. 전략 패턴(Strategy Pattern) 구현

  • 동일한 작업을 여러 방식으로 처리할 때 전략을 유연하게 교체하기 위해 사용합니다.
  • 예:
    • 데이터 정렬 전략(퀵소트, 머지소트 등).
    • AI 모델 학습/추론 시 다양한 손실 함수나 최적화 알고리즘 적용.

코드 예시: 전략 패턴

class SortStrategy:
    def sort(self, data):
        raise NotImplementedError("Subclasses must implement this method")

class QuickSort(SortStrategy):
    def sort(self, data):
        return sorted(data)  # 간단히 구현

class MergeSort(SortStrategy):
    def sort(self, data):
        return sorted(data)  # 간단히 구현

def perform_sort(strategy, data):
    return strategy.sort(data)

data = [5, 2, 9, 1]

quick_sort = QuickSort()
merge_sort = MergeSort()

print(perform_sort(quick_sort, data))  # QuickSort 사용
print(perform_sort(merge_sort, data))  # MergeSort 사용

 

3. 다양한 데이터 타입 처리

  • 동일한 함수가 다양한 데이터 타입에 대해 동작하도록 구현할 수 있습니다.
  • 예: Python의 len() 함수는 문자열, 리스트, 튜플 등 다양한 타입에 대해 동작.

코드 예시: 데이터 처리

class DataProcessor:
    def process(self, data):
        raise NotImplementedError("Subclasses must implement this method")

class TextDataProcessor(DataProcessor):
    def process(self, data):
        return data.lower()

class NumberDataProcessor(DataProcessor):
    def process(self, data):
        return sum(data)

processors = [TextDataProcessor(), NumberDataProcessor()]

for processor in processors:
    print(processor.process("Hello" if isinstance(processor, TextDataProcessor) else [1, 2, 3]))

 

4. GUI나 게임 개발

  • 버튼, 텍스트 필드, 이미지 등 다양한 UI 요소가 공통된 인터페이스를 통해 동작.
  • 캐릭터, 무기, 몬스터 등 다양한 객체가 동일한 행동(공격, 이동)을 다르게 구현.

 

언제 다형성을 사용하면 좋은가?

  • 유지보수가 쉬운 코드가 필요할 때.
  • 새로운 기능이 자주 추가되는 프로젝트에서.
  • 동일한 작업을 여러 방식으로 처리해야 하는 경우.
  • 서로 다른 객체들이 공통된 인터페이스나 기반 클래스를 공유할 때.

이처럼 다형성은 코드 구조를 체계적으로 잡아주고, 변경 사항에도 강한 유연성을 제공하기 때문에 큰 규모의 프로젝트나 확장이 빈번한 시스템에서 유용합니다. Python의 동적 타이핑(dynamic typing) 특성과 결합하면 매우 강력한 도구가 될 수 있습니다.

반응형
Comments