티스토리 뷰

Python

파이썬 매직 메서드(Magic Methods)

4OurFuture 2025. 7. 26. 15:35
728x90
반응형

파이썬에는 클래스에 특별한 기능을 자연스럽게 추가할 수 있도록 돕는 매직 메서드(스페셜 메서드)가 있습니다. __add__, __len__ 등 더블 언더스코어(__)로 감싸인 메서드를 구현함으로써, 사용자 정의 클래스도 파이썬의 내장 타입처럼 동작하게 할 수 있습니다.


1. 매직 메서드란?

  • 정의: 메서드 이름이 __method__ 형태인 특별한 메서드로, 연산자나 내장 함수 호출 시 자동으로 실행됩니다.
  • 효과: len(obj), obj[key], obj + other 등 내장 동작을 클래스에 직접 연결할 수 있습니다.

매직 메서드를 사용하는 이유

  • 코드의 직관성을 높입니다. 예: len(data) vs data.length().
  • 일관된 인터페이스를 제공합니다. 리스트, 딕셔너리, 문자열과 같은 기본 타입 경험을 사용자 객체에도 적용할 수 있습니다.

2. 자주 쓰이는 매직 메서드 모음

2-1. 컬렉션 관련

  • __len__(self)len(obj) 호출 시 실행됩니다.
  • __getitem__(self, key)obj[key] 조회 시 실행됩니다.
  • __setitem__(self, key, value)obj[key] = value 할당 시 실행됩니다.
  • __iter__(self)for x in obj 반복(iteration) 시 실행됩니다.
  • __contains__(self, item)item in obj 검사 시 실행됩니다.

2-2. 표현 및 호출 관련

  • __str__(self)str(obj) 또는 print(obj) 시 객체의 "사용자 친화적" 문자열을 반환합니다.
  • __repr__(self) → 인터프리터나 개발자가 보는 "공식" 객체 표현을 반환합니다. 가능한 한 해당 객체를 다시 생성할 수 있는 문자열을 제공합니다.
  • __call__(self, *args, **kwargs)obj()처럼 객체를 함수처럼 호출할 때 실행됩니다.

2-3. 연산 및 비교 관련. 연산 및 비교 관련

  • 산술: __add__, __sub__, __mul__, __truediv__, __mod__
  • 비교: __eq__, __ne__, __lt__, __gt__, __le__, __ge__
  • 비트 연산: __and__, __or__, __xor__, __lshift__, __rshift__
  • 단항 연산: __neg__, __pos__, __invert__

3. 매직 메서드 구현 예제

아래 예제에서는 각 메서드를 직접 구현하면서 동작 방식을 확인합니다.

3-1. 길이를 지원하는 커스텀 리스트

class MyList:
    def __init__(self, data):
        self._data = list(data)

    def __len__(self):
        return len(self._data)

    def __getitem__(self, idx):
        return self._data[idx]

    def __iter__(self):
        return iter(self._data)

    def __str__(self):
        return f"MyList({self._data})"

# 사용 예시
ml = MyList([10, 20, 30])
print(len(ml))      # 3입니다.
print(ml[1])        # 20입니다.
for x in ml:
    print(x)        # 10, 20, 30 순차 출력합니다.

3-2. 키-값 저장소처럼 동작하는 클래스

class KeyValueStore:
    def __init__(self):
        self._store = {}

    def __setitem__(self, key, value):
        self._store[key] = value

    def __getitem__(self, key):
        return self._store.get(key)

    def __contains__(self, key):
        return key in self._store

    def __str__(self):
        return str(self._store)

# 사용 예시
kv = KeyValueStore()
kv['a'] = 100
print(kv['a'])      # 100입니다.
print('b' in kv)    # False입니다.

3-3. 호출 가능한 객체

class Greeter:
    def __init__(self, name):
        self.name = name

    def __call__(self, greeting):
        return f"{greeting}, {self.name}!"

# 사용 예시
g = Greeter("Alice")
print(g("Hello"))  # Hello, Alice!입니다.

3-4. 커스텀 벡터 연산

class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        if not isinstance(other, Vector):
            return NotImplemented
        return Vector(self.x + other.x, self.y + other.y)

    def __repr__(self):
        # 개발자용 공식 표현: 객체를 recreatable 한 문자열로 제공합니다
        return f"Vector(x={self.x}, y={self.y})"

    def __str__(self):
        # 사용자용 친화적 표현
        return f"Vector({self.x}, {self.y})"

# 사용 예시
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)         # Vector(4, 6)입니다.
print(repr(v1 + v2))   # Vector(x=4, y=6)입니다.

3-5. __repr__ 예제

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __repr__(self):
        return f"Person(name='{self.name}', age={self.age})"

p = Person("Bob", 30)
print(p)  # Person(name='Bob', age=30)입니다.
# 인터프리터에서 객체를 직접 입력하면 __repr__ 결과가 출력됩니다.
# >>> p
# Person(name='Bob', age=30)

4. 클래스 오버로딩 관점에서 매직 메서드 이해하기

클래스 오버로딩은 매직 메서드를 통해 구현됩니다. 즉, 연산자나 내장 함수에 대응하는 메서드를 클래스 내부에 정의함으로써, 객체가 해당 연산자나 함수를 호출할 때 원하는 동작을 수행하도록 하는 것입니다.

  1. 명시적 메서드 대신 자연스러운 문법 제공
    • 예: data + other 대신 data.__add__(other) 호출이 자동으로 일어납니다.
  2. 다형성(Polymorphism)
    • 동일한 연산자지만, 객체의 타입에 따라 다른 동작을 수행하도록 커스터마이징 가능합니다.
  3. 단일 책임 원칙 활용
    • 매직 메서드마다 한 가지 연산 책임을 집중시켜, 클래스 설계가 명확해집니다.
  4. 확장성
    • 새로운 연산자나 시퀀스 동작이 필요할 때마다 대응 매직 메서드를 추가하여 기능을 확장할 수 있습니다.

5. 요약 및 팁

  • 매직 메서드는 클래스 오버로딩의 핵심 도구입니다.
  • 자주 쓰는 메서드부터 하나씩 구현해 보세요: __len__, __getitem__, __add__, __call__
  • 각 메서드는 단일 책임 원칙에 따라 구현합니다.
  • 다형성을 활용해 다양한 타입에 통일된 인터페이스를 제공할 수 있습니다.

파이썬 매직 메서드를 적극 활용하여, 사용자 정의 클래스가 더욱 직관적이고 유연하게 동작하도록 설계해 보시기 바랍니다.

728x90
반응형