서론
흔히들 파이썬(Python)은 자바(Java)와 비교하였을 때 보다 개발하기 쉬운 언어라고들 한다.
파이썬이 개발하기 쉬운 언어로 평가받는 이유 중 하나는 다양한 연산자들이 직관적이고 유연하게 설계되어 있기 때문이다.
일례로, 리스트 자료형의 경우 'in' 연산자를 통해 해당 리스트 내부에 특정 값이 존재하는지를 확인할 수 있다.
fruits = ['apple', 'banana', 'cherry']
print('banana' in fruits)
> 출력 : True상기 예시를 보았을 때 파이썬 언어를 모르는 사람을 데려와도 무슨 코드인지 해석할 수 있을 것이다.
본 글에서는 이러한 연산자가 동작하는 원리에 대해서 보다 자세하게 알아보고자 한다.
본론
이전보다 한층 진일보하신(o1 모델) ChatGPT님께 자문을 구하였다
일반적으로 이름이 두 개의 밑줄(__)로 시작하고 끝납니다.
이러한 메서드는 파이썬의 내장 함수나 연산자와 상호 작용하여 객체의 동작을 커스터마이징할 수 있게 해 줍니다.
매직 메서드를 활용하면 사용자 정의 객체가 파이썬의 기본 동작과 자연스럽게 통합될 수 있습니다.
출처 | OpenAI. (2025). ChatGPT (o1 Version) [Large language model]. https://chat.openai.com
매직 메서드(Magic Method)란?
파이썬의 매직 메서드(Magic Methods)는 클래스 내에서 특정 기능을 수행하기 위해 미리 정의된 메서드들을 말한다.
주로 이름 앞뒤에 밑줄(__)이 두 개씩 붙어 있어 __init__, __str__, __contains__ 등과 같은 형태로 나타나며, 이를 '던더(Dunder) 메서드'라고도 부른다.
이러한 매직 메서드들은 파이썬의 다양한 내장 함수나 연산자가 해당 객체와 상호 작용할 때 호출되며, 이를 통해 객체의 동작을 유연하게 커스터마이징할 수 있게 된다.
예컨대, 'in' 연산자는 내부적으로 __contains__ 매직 메서드를 찾고 호출한다.
'in' 연산자와 List 자료형
앞서 예제를 통해 언급한 'in' 연산자를 보다 구체적으로 살펴보면 다음과 같다.
파이썬에서 a in b 구문이 수행될 때, 인터프리터는 내부적으로 가장 먼저 b.__contains__(a)를 확인한다.
- 만약
__contains__메서드가 정의되어 있다면, 그 메서드를 바로 호출하여 그 결과(True/False)에 따라 'in' 연산의 결과가 결정된다. __contains__가 없을 경우, 파이썬은 b가 이터러블(iterable)한지 확인한 뒤,__iter__혹은__getitem__을 통해 루프를 돌며 요소를 하나씩 비교하는 방식으로 포함 여부를 판별한다.
즉 'in' 연산자는 내부적으로 __contains__에 우선순위를 두고 동작하며, 만약 구현이 없다면 반복(iteration)을 통해 동작한다.
class FruitBasket:
def __init__(self, fruits):
self.fruits = fruits
def __contains__(self, item):
return item in self.fruits # 리스트의 in 연산자 재활용
basket = FruitBasket(['apple', 'banana', 'cherry'])
print('banana' in basket) # basket.__contains__('banana') 호출
> 출력: True매직 메서드와 연산자
파이썬에는 이 밖에도 여러 매직 메서드들이 존재한다. 대표적인 것들을 살펴보면 다음과 같다.
__getitem__,__setitem__,__delitem__- obj[i], obj[i] = value, del obj[i] 같은 인덱스 기반 연산을 제어할 수 있음.
__len__- len(obj) 호출 시 내부적으로 obj.__len__()이 실행됨.
__iter__- for x in obj: 구조의 반복문을 사용할 수 있게 해 줌.
- 연산자 오버로딩 (Operator Overloading)
- __add__( + ), __sub__( - ), __mul__( * ), __eq__( == ), __lt__( < ) 등 다양한 메서드를 통해 사용자 정의 객체에서도 수학 연산이나 비교 연산을 오버로딩할 수 있다.
이처럼 매직 메서드를 활용함으로써, 사용자 정의 객체를 파이썬의 기본 문법(연산자)과 자연스럽게 결합할 수 있다.
보다 자세한 정보는 아래 공식 문서를 통해 확인할 수 있다.

자료형 인스턴스와 매직 메서드
파이썬에서 모든 것은 객체이며, 각 객체는 특정한 자료형(클래스) 의 인스턴스이다.
이 말은 파이썬뿐만 아니라, 자바와 같은 객체 지향 언어를 접할 때도 자주 듣게 될 것이다.
풀어서 말하자면, 파이썬에서 사용하는 모든 정수나 문자 타입의 변수는 내장 자료형 클래스에서 파생된 인스턴스라는 뜻이다. 마찬가지로 리스트(list), 튜플(tuple), 딕셔너리(dict) 등 역시 모두 파이썬의 내장 자료형 클래스에서 파생된 인스턴스들이다.
이러한 내장 자료형들은 이미 내부적으로 여러 매직 메서드를 구현해 두었기 때문에, in, len(), 인덱스 접근 등과 같은 다양한 기능을 별도 구현 없이 자연스럽게 사용할 수 있다.
마찬가지로, 사용자 정의 클래스에서도 적절한 매직 메서드를 구현해 놓으면, 내장 자료형처럼 in 연산자, 인덱스 접근, 슬라이싱, 연산자 오버로딩 등을 적용할 수 있다.
이는 파이썬이 객체 지향 프로그래밍을 직관적으로 지원하는 데 큰 역할을 한다.
함수의 호출
추가로, 파이썬에서 함수를 호출할 때 괄호 ( )를 사용하는 것도 사실은 __call__이라는 매직 메서드를 통해 이루어진다. 즉, 함수나 람다, 메서드, 혹은 __call__을 정의한 클래스의 인스턴스는 이 매직 메서드를 통해 ( )를 사용한 호출 연산을 가능하게 한다.
class Fruit:
def __init__(self, name):
self.name = name
def __call__(self):
print(f'{self.name}가 호출됨')
apple = Fruit('사과')
apple()
> 출력 : 사과가 호출됨참고자료
