728x90
반응형
Overview
매직 메서드(Magic Methods)는 Python 클래스에 특별한 기능을 부여하는 메서드다. ` __init__`, `__str__` 처럼 앞뒤로 언더스코어 두 개(__)가 붙어서 던더(Dunder) 메서드라고도 불린다.
매직 메서드를 사용하면 클래스가 Python의 내장 함수나 연산자와 자연스럽게 동작하게 만들 수 있다.

1. 객체 생성과 초기화
`__init__`: 생성자
가장 많이 사용하는 매직 메서드로, 객체가 생성될 때 자동으로 호출된다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"{name} 객체가 생성되었습니다!")
person = Person("철수", 25)
# 출력: 철수 객체가 생성되었습니다!
`__new__`: 인스턴스 생성
`__init__` 보다 먼저 호출되며, 실제로 객체를 생성하는 메서드다. 싱글톤 패턴 등에서 사용된다.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True - 같은 객체!
2. 문자열 표현
`__str__`: 사용자 친화적 문자열
`print()` 함수나 `str()` 로 객체를 출력할 때 사용된다.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"'{self.title}' by {self.author}"
book = Book("파이썬 완벽 가이드", "홍길동")
print(book) # '파이썬 완벽 가이드' by 홍길동
`__repr__`: 개발자용 문자열
디버깅할 때 유용하며, `repr()` 함수나 인터프리터에서 객체를 직접 입력했을 때 사용된다.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __str__(self):
return f"({self.x}, {self.y})"
point = Point(3, 4)
print(point) # (3, 4) - __str__ 사용
print(repr(point)) # Point(x=3, y=4) - __repr__ 사용
차이점: `__str__` 은 일반 사용자용, `__repr__` 은 개발자용으로 더 자세한 정보를 담는다.
3. 비교 연산자
모든 비교 연산자 구현하기
class Money:
def __init__(self, amount):
self.amount = amount
def __eq__(self, other):
"""=="""
return self.amount == other.amount
def __ne__(self, other):
"""!="""
return self.amount != other.amount
def __lt__(self, other):
"""<"""
return self.amount < other.amount
def __le__(self, other):
"""<="""
return self.amount <= other.amount
def __gt__(self, other):
""">"""
return self.amount > other.amount
def __ge__(self, other):
""">="""
return self.amount >= other.amount
money1 = Money(1000)
money2 = Money(2000)
print(money1 < money2) # True
print(money1 == money2) # False
print(money1 >= money2) # False
팁: `functools.total_ordering` 데코레이터를 사용하면 `__eq__` 와 `__lt__` 만 구현해도 나머지가 자동 생성된다!
from functools import total_ordering
@total_ordering
class Money:
def __init__(self, amount):
self.amount = amount
def __eq__(self, other):
return self.amount == other.amount
def __lt__(self, other):
return self.amount < other.amount
# 이제 >, <=, >= 도 자동으로 사용 가능!
4. 산술 연산자
기본 산술 연산
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 __sub__(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 __truediv__(self, scalar):
"""/"""
return Vector(self.x / scalar, self.y / scalar)
def __repr__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(1, 1)
print(v1 + v2) # Vector(3, 4)
print(v1 - v2) # Vector(1, 2)
print(v1 * 2) # Vector(4, 6)
print(v1 / 2) # Vector(1.0, 1.5)
복합 할당 연산자
class Counter:
def __init__(self, value=0):
self.value = value
def __iadd__(self, other):
"""+="""
self.value += other
return self
def __isub__(self, other):
"""-="""
self.value -= other
return self
counter = Counter(10)
counter += 5
print(counter.value) # 15
counter -= 3
print(counter.value) # 12
5. 컨테이너 매직 메서드
리스트처럼 동작하는 클래스 만들기
class CustomList:
def __init__(self):
self._items = []
def __len__(self):
"""len() 함수"""
return len(self._items)
def __getitem__(self, index):
"""obj[index]"""
return self._items[index]
def __setitem__(self, index, value):
"""obj[index] = value"""
self._items[index] = value
def __delitem__(self, index):
"""del obj[index]"""
del self._items[index]
def __contains__(self, item):
"""item in obj"""
return item in self._items
def append(self, item):
self._items.append(item)
my_list = CustomList()
my_list.append(1)
my_list.append(2)
my_list.append(3)
print(len(my_list)) # 3
print(my_list[0]) # 1
print(2 in my_list) # True
my_list[1] = 10
print(my_list[1]) # 10
6. 호출 가능한 객체
`__call__`: 객체를 함수처럼 호출
class Multiplier:
def __init__(self, factor):
self.factor = factor
def __call__(self, x):
return x * self.factor
double = Multiplier(2)
triple = Multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
# 객체를 함수처럼 사용 가능!
실전 예제: 데코레이터를 클래스로 구현
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"{self.func.__name__} 호출 횟수: {self.count}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello() # say_hello 호출 횟수: 1, Hello!
say_hello() # say_hello 호출 횟수: 2, Hello!
say_hello() # say_hello 호출 횟수: 3, Hello!
7. 컨텍스트 매니저
`__enter__` 와 `__exit__: with `문 지원
class FileManager:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
self.file = None
def __enter__(self):
print(f"파일 열기: {self.filename}")
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
print("파일 닫기")
if self.file:
self.file.close()
# with 문과 함께 사용
with FileManager('test.txt', 'w') as f:
f.write("Hello, World!")
# 자동으로 파일이 닫힘!
8. 실전 예제: 좌표 클래스
모든 개념을 활용한 완전한 예제다.
from functools import total_ordering
import math
@total_ordering
class Point:
"""2D 좌표를 표현하는 클래스"""
def __init__(self, x, y):
self.x = x
self.y = y
# 문자열 표현
def __str__(self):
return f"({self.x}, {self.y})"
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
# 비교 연산
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __lt__(self, other):
# 원점으로부터의 거리로 비교
return self.distance_from_origin() < other.distance_from_origin()
# 산술 연산
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Point(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Point(self.x * scalar, self.y * scalar)
# 기타 유용한 메서드
def __abs__(self):
"""abs(point) - 원점으로부터의 거리"""
return self.distance_from_origin()
def __bool__(self):
"""bool(point) - 원점이 아니면 True"""
return self.x != 0 or self.y != 0
def distance_from_origin(self):
return math.sqrt(self.x**2 + self.y**2)
# 사용 예시
p1 = Point(3, 4)
p2 = Point(1, 2)
print(p1) # (3, 4)
print(repr(p1)) # Point(x=3, y=4)
print(p1 + p2) # (4, 6)
print(p1 - p2) # (2, 2)
print(p1 * 2) # (6, 8)
print(p1 == p2) # False
print(p1 > p2) # True
print(abs(p1)) # 5.0
print(bool(Point(0, 0))) # False
print(bool(p1)) # True
주요 매직 메서드 정리
| 카테고리 | 메서드 | 설명 |
| 생성/소멸 | `__init__` | 객체 초기화 |
| `__new__` | 객체 생성 | |
| `__del__` | 객체 소멸 시 | |
| 문자열 | `__str__` | str(), print() |
| `__repr__` | repr(), 인터프리터 | |
| 비교 | `__eq__` | == |
| `__ne__` | != | |
| `__lt__` | < | |
| `__le_` | <= | |
| `__gt__` | > | |
| `__ge__` | >= | |
| 산술 | `__add__` | + |
| `__sub__` | - | |
| `__mul__` | * | |
| `__truediv__` | / | |
| `__floordiv__` | // | |
| `__mod__` | % | |
| `__pow__` | ** | |
| 컨테이너 | `__len__` | len() |
| `__getitem__` | obj[key] | |
| `__setitem__` | obj[key] = val | |
| `__delitem__` | del obj[key] | |
| `__contains__` | item in obj | |
| 기타 | `__call__` | obj() |
| `__enter__` | with 문 진입 | |
| `__exit__` | with 문 종료 | |
| `__bool__` | bool() | |
| `__hash__` | hash() |
결론
매직 메서드를 활용하면
- 클래스를 Python의 내장 타입처럼 자연스럽게 사용 가능
- 연산자 오버로딩으로 직관적인 코드 작성
- 더 Pythonic하고 읽기 쉬운 코드
- 강력한 추상화와 캡슐화
매직 메서드는 Python의 객체지향 프로그래밍을 한 단계 업그레이드시켜주는 핵심 기능이다!
Reference
- Python Official Docs - Data Model (Special Methods): https://docs.python.org/3/reference/datamodel.html
튜토리얼 & 가이드
- Real Python - Magic Methods: https://realpython.com/python-magic-methods/
- GeeksforGeeks - Dunder Methods: https://www.geeksforgeeks.org/python/dunder-magic-methods-python/
- Rafe Kettler - Magic Methods Guide: https://rszalski.github.io/magicmethods/
- dbader.org - Dunder Methods: https://dbader.org/blog/python-dunder-methods
- Python Morsels - Every Dunder Method: https://www.pythonmorsels.com/every-dunder-method/
- TutorialsTeacher - Magic Methods: https://www.tutorialsteacher.com/python/magic-methods-in-python
- Built In - Dunder Methods: https://builtin.com/data-science/dunder-methods-python
728x90
반응형
'Launguage' 카테고리의 다른 글
| Python 예외 처리와 컨텍스트 매니저 완벽 가이드 (0) | 2025.12.19 |
|---|---|
| Python 상속과 다형성 완벽 가이드 (0) | 2025.12.05 |
| Python 클래스 데코레이터 완벽 가이드 (0) | 2025.11.21 |
| Python 메서드의 3가지 종류: Instance, Class, Static Method 완벽 정리 (1) | 2025.10.24 |
| Python 가상환경 설정(WSL2 Ubuntu) (0) | 2023.10.10 |