매직 메서드
1. 매직 메서드
파이썬의 클래스에는 특별한 메서드가 있습니다. 파이썬에서는 이 특별한 메서드를 쉽게 재정의하여 사용할 수 있게 되어있습니다. 예를 들어, +
연산자를 만나면 __add__
메서드가 호출됩니다. 이렇게 미리 파이썬 인터프리터에 정의되어 있는 메서드를 사용자가 재정의할 수 있도록 해놓은 것이죠. 아래 return문을 여러 값으로 수정해보세요.
마치 마법처럼 간단하게 수정할 수 있다고 해서 매직 매서드라고 부릅니다. 혹은 더블 언더바(__)를 2개 쓰고 있는 점에서 던더(dunder) 메서드라고도 부릅니다.
이러한 매직 메서드는 CPython에 구현되어 있습니다. 우리가 작성한 코드는 바이트 코드로 변환되어 CPython에 의해 실행됩니다. 더하기는 3.11버전부터는 BINARY_OP
(이전에는BINARY_ADD
)라는 바이트 코드로 변환되어 실행되며 이 연산자의 실제 구현은 아래 CPython 소스코드에서 확인할 수 있습니다.
바이너리 코드 확인은 아래 코드로 가능합니다.
좀 더 구체적으로 매직 메서드를 살펴보겠습니다. 좌표평면의 점을 class로 구현해보았습니다.
+
부호를 사용하여 덧셈을 할 때 dot1의 __add__
메직메서드가 실행됩니다. print로 self의 x좌표와 y좌표를 출력함으로 알 수 있습니다.
매직 메서드 __init__
은 앞에서도 살펴보았습니다. 이 매직 메서드는 인스턴스가 생성이 될 때 호출됩니다. 위 코드에서는 dot1과 dot2 인스턴스가 생성이 될 때 호출됩니다. 여기서 (10, 20)
, (20, 30)
은 각각 인스턴스의 영역 self에 등록됩니다.
마찬가지로 곱하기도 구현할 수 있습니다. 곱하기는 __mul__
로 구현할 수 있습니다. 다만 실제 곱하기를 구현하지는 않았습니다. 이는 실제 곱하기를 구현하지 않아도 된다는 것을 보여드리기 위함입니다.
이번에는 행렬의 연산을 구현한 예시로 살펴보도록 하겠습니다.
위와 같은 예시를 통해 행렬의 덧셈, 뺄셈, 곱셈 등을 구현할 수도 있습니다.
이렇게 부호들은 클래스의 메직메서드와 연결되어 있습니다. 연산에 관련된 매직 메서드 공식 문서는 아래와 같습니다.
Data model (매직 메서드)2. 주요한 매직 메서드
좀 더 상세한 매직 메서드는 다음 챕터부터 다룹니다. 여기서는 주요한 매직 메서드를 간단히 살펴보겠습니다.
2.1. 생성자와 소멸자
__init__(self, ...)
: 객체가 생성될 때 호출되는 생성자 메서드__del__(self)
: 객체가 소멸될 때 호출되는 소멸자 메서드
2.2. 문자열 표현
__str__(self)
:str()
함수 출력 결과와 같습니다. 이는 print로 출력되는 결과와도 동일합니다. 이 출력은 "공식적이지 않은" 또는 "좋게 보이는" 문자열 표현을 반환합니다. 객체의 공식적인 표현은 repr입니다.__repr__(self)
:repr()
함수의 출력 결과와 같습니다. 객체의 "공식적인" 문자열 표현을 반환합니다.
2.3. 산술 연산
__add__(self, other)
: 덧셈 연산__sub__(self, other)
: 뺄셈 연산__mul__(self, other)
: 곱셈 연산__truediv__(self, other)
: 나눗셈 연산(/)
2.4. 비교 연산
__eq__(self, other)
: 동등 연산 (==)__ne__(self, other)
: 부등 연산 (!=)
2.5. 컨테이너 타입 연산
__len__(self)
:len()
함수의 출력 결과와 같습니다.__getitem__(self, key)
: 인덱싱 연산 (obj[key])의 출력 결과와 같습니다.__setitem__(self, key, value)
: 항목 할당__contains__(self, value)
:in
연산자
2.6. 호출 가능 객체
__call__(self, ...)
: 객체를 함수처럼 호출할 때 사용됩니다.
이 밖에도 많은 매직 메서드들이 있습니다. 이 메서드들을 오버라이드하여 사용자 정의 클래스의 동작을 원하는 대로 정의할 수 있습니다.
3. 매직 메서드 설계 철학
우리는 매직 메서드를 사용함으로 여러 이점을 얻을 수 있습니다.
- 개발자는 간단한 기능의 메서드는 매직 메서드를 사용해 구현하면되며, 사용자는 이를 외우지 않고 편하게 사용할 수 있습니다.
예를 들어, 다른 언어처럼 문자열 변환을 위해 커스텀자료형.toString()
등에 메서드를 만들어야 하는 번거로움을 줄일 수 있습니다. print로 출력할 때에는 __str__
을, 객체 자체를 출력할 때에는 __repr__
을 사용하면 됩니다. 사용자가 이를 외워 사용할 필요도 없습니다. 파이썬 기본 자료형처럼 사용하면 됩니다.
- 일관된 문법을 보장할 수 있습니다.
- 리스트의 길이를 알고 싶을 때:
len([1,2,3])
- 문자열의 길이를 알고 싶을 때:
len("hello")
- 세트의 길이를 알고 싶을 때:
len({1,2,3})
이처럼 파이썬의 기본 문법을 사용하면 됩니다. 사용자는 각 자료형이 커스텀자료형.length
등을 제공하는지 살펴볼 필요가 없습니다. 파이썬 기본 자료형처럼 사용하면 됩니다.
개발하는 입장에서도 길이를 제공하고 싶을 때 인스턴스 변수나 메서드를 만들 필요도 없습니다. __len__
을 사용하면 됩니다.
- 파이썬의 기본 문법을 사용할 수 있는 인스턴스를 만들 수 있습니다.
순회 가능한 객체나 슬라이싱이 가능한 객체를 구현하고자 할 때 해당 객체를 상속받아 구현하는 것이 아니라 매직 메서드를 구현하는 것만으로도 기본문법이 작동하는 코드를 작성할 수 있습니다.
- 사용자가 이해하기 쉽습니다.
새로 접하는 자료형을 사용할 때에도 dir()
에 정의된 매직 메서드를 확인하여 이 자료형이 어떤 기능이 있는지 대략적으로 짐작할 수 있습니다.