한양과학기술고등학교

에듀테크 프로젝트 대시보드

매직 메서드 (dunder)

__repr__ __eq__ __len__ __getitem__ __iter__

__name__ 형태의 메서드로 내장 연산자·함수와 클래스를 연결합니다.

1. 표현·비교

class Money:
    def __init__(self, cents):
        self.cents = cents
    def __repr__(self):
        return f"Money({self.cents})"
    def __eq__(self, other):
        return isinstance(other, Money) and self.cents == other.cents
    def __hash__(self):              # __eq__ 정의하면 __hash__ 도 (set/dict 키용)
        return hash(self.cents)
    def __lt__(self, other):         # < 정의하면 sorted 가능
        return self.cents < other.cents

sorted([Money(300), Money(100)])

2. 산술 연산자

class Vec:
    def __init__(self, x, y): self.x, self.y = x, y
    def __add__(self, o):  return Vec(self.x + o.x, self.y + o.y)
    def __sub__(self, o):  return Vec(self.x - o.x, self.y - o.y)
    def __mul__(self, k):  return Vec(self.x * k, self.y * k)
    def __repr__(self):    return f"Vec({self.x}, {self.y})"

Vec(1, 2) + Vec(3, 4)      # => Vec(4, 6)
Vec(1, 2) * 3              # => Vec(3, 6)

# __radd__, __iadd__ 등도 있음 (역방향, in-place)

3. 컨테이너처럼 동작

class Playlist:
    def __init__(self):
        self._songs = []
    def __len__(self):              # len(pl)
        return len(self._songs)
    def __getitem__(self, i):       # pl[i], 슬라이싱, 반복도 가능
        return self._songs[i]
    def __setitem__(self, i, v):
        self._songs[i] = v
    def __contains__(self, song):   # song in pl
        return song in self._songs

pl = Playlist()
len(pl); pl[0]; "곡" in pl

4. 반복 프로토콜

class Countdown:
    def __init__(self, start): self.start = start
    def __iter__(self):
        n = self.start
        while n > 0:
            yield n                 # 제너레이터로 간단히
            n -= 1

for x in Countdown(3):              # => 3, 2, 1
    print(x)
list(Countdown(3))

5. 호출·컨텍스트

class Multiplier:
    def __init__(self, factor): self.factor = factor
    def __call__(self, x):          # 인스턴스를 함수처럼 호출
        return x * self.factor

double = Multiplier(2)
double(10)         # => 20

class Timer:
    def __enter__(self):            # with 블록 진입
        self.start = time.perf_counter(); return self
    def __exit__(self, *exc):       # 나갈 때 (예외 정보 3개)
        print(time.perf_counter() - self.start)

6. 자주 쓰는 dunder 요약

메서드트리거
__init__ / __new__생성
__repr__ / __str__repr() / str()·print
__eq__ __lt__ …== < 비교
__hash__set·dict 키
__len__ __bool__len() / truthiness
__getitem__ __iter__인덱싱 / 반복
__call__인스턴스 호출
__enter__ __exit__with
"There should be one — and preferably only one — obvious way to do it"