Python

매직 메서드

gudwns5533 2026. 5. 29. 21:29

매직 메서드(magic method)는 파이썬에서 특정 문법이나 연산이 실행될 때 자동으로 호출되는 특별한 메서드로, __len__, __str__, __getitem__처럼 양쪽에 밑줄(__)이 붙는 형태를 가진다. 이 메서드들은 클래스에 구현하면 len(obj), print(obj), obj[0], obj + obj 같은 파이썬의 기본 문법과 자연스럽게 연결되어 객체의 동작을 직접 정의할 수 있다. 즉, 매직 메서드는 객체를 리스트처럼 사용하거나, 연산을 수행하거나, 출력 형태를 바꾸는 등 파이썬의 문법과 객체를 이어주는 핵심 기능이다.

매직 메서드의 사용이유

 

파이썬에는 이미 훌륭한 내장 타입과 함수들이 있지만, 기존 내장 타입의 기능만으로는 내가 원하는 규칙이나 비즈니스 로직을 표현할 수 없기 때문에 매직 메서드를 사용한다. 내장 함수의 편리함은 그대로 유지하면서, 그 안에 나만의 '커스텀 규칙'을 넣고 싶을 때 매직 메서드를 사용해 클래스를 만든다.

객체 출력

 

1. __str__()

 

__str__()는 객체를 사람이 읽기 쉬운 문자열로 표현하기 위해 사용하는 매직 메서드로, print(obj)나 str(obj)가 호출될 때 자동으로 실행된다. 이 메서드를 클래스에 정의하면 객체를 출력할 때 기본 주소값 대신 원하는 형태로 내용을 보여줄 수 있어 디버깅이나 사용자 출력에 매우 유용하다.

class Fruit:
    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity

    def __str__(self):
        return f"{self.name} {self.quantity}개"       # str() 함수와 연결되어있는 매직 메서드
        
apple = Fruit('사과', 10)
print(apple)       # print(str(apple))이 생략되어있다.

# 사과 10개

 

2. __repr__()

 

__repr__()은 객체를 개발자 관점에서 정확하게 표현하는 문자열을 반환하는 매직 메서드로, 주로 디버깅이나 로그에서 사용된다. repr(obj)를 호출하거나 인터프리터에서 객체를 직접 평가할 때 자동으로 호출되며, 가능하다면 객체를 다시 생성할 수 있는 형태의 문자열을 반환하는 것이 권장된다. __str__()이 사람이 읽기 좋은 출력이라면, __repr__()은 객체의 구조와 상태를 명확하게 보여주는 공식적인 표현이다.

class Fruit:
    def __init__(self, name, quantity):
        self.name = name
        self.quantity = quantity
        
    def __str__(self):
        return f"{self.name} {self.quantity}개"

    def __repr__(self):
        return f"Fruit(name='{self.name}', quantity={self.quantity})"     # 객체를 만드는 형태의 문자열

apple = Fruit('사과', 10)
print(repr(apple))  # __repr__ 호출
print(apple)        # __str__ 없으면 __repr__ 호출  (같이있을때는 __str__이 우선시 됨)

# Fruit(name='사과', quantity=10)
# 사과 10개

제너레이터

 

제너레이터(generator)는 yield 키워드를 사용해 값을 한 번에 하나씩 생성해 반환하는 반복 객체로, 함수 형태로 간단하게 이터레이터를 만들 수 있는 파이썬의 기능이다. 일반 함수처럼 보이지만 yield를 만나면 값을 반환하면서도 실행 상태를 유지하고, 다음 호출 시 이어서 실행되기 때문에 전체 데이터를 한 번에 만들지 않고 필요할 때마다 생성할 수 있어 메모리 효율이 매우 높다.

class Counter:
    def __init__(self, max):
        self.max = max
        self.current = 0

    def __iter__(self):
        return self           # 자기 자신을 iterator로 사용

    def __next__(self):
        if self.current < self.max:
            self.current += 1
            return self.current
        else:
            raise StopIteration
            
counter = Counter(3)

# for문: iter(), next()함수를 자동으로 호출, StopIteration으로 멈춤
for num in counter:
    print(num)
    
# 1
# 2
# 3

 

👉 for문이 내부적으로 자동으로 iter()를 호출

👉 이터레이터는 이터러블로부터 실제로 값을 하나씩 꺼내는 객체로, __iter__()와 __next__() 메서드를 모두 구현.

👉 __iter__()는 반복을 시작하게 하고, __next__()는 값을 하나씩 꺼내며, 더 이상 반환할 값이 없으면 StopIteration 예외를 발생시켜 반복을 종료.

def counter(max):
    current = 0
    while current < max:
        current += 1
        yield current

for num in counter(3):
    print(num)

 

👉 yield의 의미

  • 값을 반환한다.
  • 함수 상태를 저장한다.
  • 다음 호출 시 이어서 실행한다.

👉 제너레이터는 자동으로 __iter__ + __next__를 만들어준다.


인덱싱

 

1. __getitem__()

 

__getitem__()은 객체에서 인덱스나 키를 이용해 값을 조회할 때 호출되는 매직 메서드로, obj[index] 또는 obj[key] 형태로 접근하면 자동으로 실행된다. 이 메서드를 구현하면 사용자 정의 객체도 리스트나 딕셔너리처럼 데이터를 꺼낼 수 있으며, 내부적으로는 전달된 인덱스나 키를 기반으로 값을 반환하도록 작성하면 된다.

 

2. __setitem__()

 

__setitem__()은 객체에서 인덱스나 키를 이용해 값을 할당할 때 호출되는 매직 메서드로, obj[index] = value 형태의 코드가 실행되면 자동으로 호출된다. 이 메서드를 구현하면 사용자 정의 객체에 값을 저장하거나 수정하는 동작을 제어할 수 있으며, 전달된 인덱스와 값을 이용해 내부 데이터를 업데이트 하도록 구현한다.

 

3. __delitem__()

 

__delitem__()은 객체에서 인덱스나 키를 이용해 값을 삭제할 때 호출되는 매직 메서드로, del obj[index] 형태의 코드가 실행되면 자동으로 호출된다. 이 메서드를 구현하면 사용자 정의 객체에서 특정 데이터를 삭제하는 로직을 정의할 수 있으며, 전달된 인덱스를 기반으로 내부 데이터를 제거하도록 작성한다.

class MyList:
    def __init__(self):
        self.data = []

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]
        
ml = MyList()
ml.data = [10, 20, 30]
print(ml[0])     # __getitem__ -> 10
ml[1] = 99       # __setitem__
print(ml.data)   # [10, 99, 30]
del ml[0]        # __delitem__
print(ml.data)   # [99, 30]

# 10
# [10, 99, 30]
# [99, 30]

객체를 함수, 값처럼 사용

 

1. __call__()

 

__call__()은 객체를 함수처럼 호출할 수 있게 만들어주는 매직 매서드로, obj() 형태로 객체를 실행하면 자동으로 호출된다. 이 메서드를 구현하면 클래스 인스턴스가 일반 함수처럼 동작할 수 있으며, 내부 데이터의 개수를 반환하도록 작성하면 된다.

class Multiplier:
    def __init__(self, n):
        self.n = n

    def __call__(self, x):
        return x * self.n

m = Multiplier(3)

print(m(10))  # 30

# 30

 

2. __len__()

 

__len__()은 객체의 길이를 정의하는 매직 메서드로, len(obj)를 호출할 때 자동으로 실행된다. 이 메서드를 구현하면 사용자 정의 객체도 리스트나 문자열처럼 길이를 가질 수 있으며, 내부 데이터의 개수를 반환하도록 작성하면 된다.

class Basket:
    def __init__(self):
        self.items1 = []
        self.items2 = []

    def __len__(self):
        return len(self.items1)  # __len__이 없이 print(len(b))를 출력하고자 하면 items1과 items2중 무엇인지 모르니 오류발생
    
b = Basket()
b.items1 = ["사과", "바나나", "오렌지"]
b.items2 = ["메론", "체리"]

print(len(b))

# 3

with 문

 

with 문은 파일, 네트워크, DB 연결처럼 사용 후 반드시 정리(clean-up)가 필요한 자원을 안전하게 관리하기 위한 문법으로, 블록이 시작될 때 필요한 작업을 수행하고 종료될 때 자동으로 정리 작업을 실행해준다. 이를 통해 try-finally를 직접 작성하지 않아도 되고, 예외가 발생하더라도 자원이 정상적으로 해제되도록 보장할 수 있다.

 

1. __enter__()

 

__enter__()는 with 문에 진입할 때 자동으로 호출되는 매직 메서드로, 자원을 준비하거나 초기화하는 역할을 한다. 이 메서드에서 반환한 값은 as 뒤에 변수에 할당되어 with 블록 내부에서 사용된다.

 

2. __exit__()

 

__exit__()는 with 블록이 끝날 때 자동으로 호출되는 매직 메서드로, 사용한 자원을 정리(clean-up)하는 역할을 한다. 이 메서드는 예외 발생 여부와 관계없이 반드시 실행되며, 예외가 발생한 경우에는 예외 타입, 값, traceback 정보를 인자로 받아 처리할 수 있다.

class MyResource:
    def __enter__(self):
        print("자원 열기")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("자원 정리")

with MyResource() as res:
    print("자원 사용 중")
    
# 자원 열기
# 자원 사용 중
# 자원 정리
class MyResource:
    def __enter__(self):
        print("자원 열기")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("자원 정리")
        print("예외 타입:", exc_type)

with MyResource():
    print("작업 중")
    # 1 / 0  # 에러 발생

# 👉 에러가 나도 __exit__()는 반드시 실행됩니다.
# 자원 열기
# 작업 중
# 자원 정리
# 예외 타입: None

'Python' 카테고리의 다른 글

모듈  (0) 2026.06.01
예외처리  (0) 2026.05.29
객체지향 프로그램 4대 패러다임  (1) 2026.05.28
객체지향 프로그래밍  (0) 2026.05.28
사용자 정의 함수 part2  (0) 2026.05.28