Python

[Python] 특수 메서드 (Magic Method)

비번변경 2024. 5. 16. 01:26

개요

Python으로 정의된 클래스를 보면 __init__, __str__ 등과 같이 메서드 이름 앞뒤에 밑줄(__)이 붙어있는 메서드가 존재한다. 이러한 메서드를 특수 메서드라고 하는데, 이 글에서는 관련 개념을 정리해두려고 한다.

 

 

특수 메서드

특수 메서드 또는 매직 메서드 (Magic Method)란 객체 지향 프로그래밍을 할 때 사용하는 특별한 메서드이다. 클래스 객체가 생성될 때, 삭제될 때, 어떤 연산자를 만났을 때 등의 각각의 상황에서 동작하도록 정해진 메서드를 특수 메서드라고 일컫는다.

2024.04.22-[Python] 클래스와 생성자에서 살펴봤던 __init__ 함수는 대표적인 특수 메서드로, 클래스 객체가 생성될 때 동작한다. __init__ 함수 외에도 문자열로 변환할 때 사용하는 __str__ 함수, 객체가 삭제될 때 호출되는 __del__ 함수, 덧셈 연산자를 만났을 때 호출되는 __add__ 함수 등 여러 특수 메서드가 존재한다.

 

아래는 특수 메서드 목록을 나열한 것이다.

 

문자열 변환 시 사용되는 특수 메서드

객체를 print문을 사용해 출력하는 등의 문자열로 표현해야 할 때 사용하는 메서드이다.

str(a)      a.__str__()
repr(a)     a.__repr__()

 

비교 연산자 사용 시 호출되는 특수 메서드

a < b       a.__lt__()
a <= b      a.__le__()
a == b      a.__eq__()
a != b      a.__ne__()
a > b       a.__gt__()
a >= b      a.__ge__()

 

수학 연산자 사용 시 호출되는 특수 메서드

a + b       a.__add__(b)
a - b       a.__sub__(b)
a * b       a.__mul__(b)
a / b       a.__truediv__(b)
a // b      a.__floordiv__(b)
a % b       a.__mod__(b)
a << b      a.__lshift__(b)
a >> b      a.__rshift__(b)
a & b       a.__and__(b)
a | b       a.__or__(b)
a ^ b       a.__xor__(b)
a ** b      a.__pow__(b)
-a          a.__neg__()
~a          a.__invert__()
abs(a)      a.__abs__()

 

항목 접근을 위한 특수 메서드

len(x)      x.__len__()
x[a]        x.__getitem__(a)
x[a] = v    x.__setitem__(a,v)
del x[a]    x.__delitem__(a)

 

만약 사용자 정의 클래스 내에서 정의하지 않은 특수 메서드를 사용하면 부모 클래스 또는 최상위 클래스인 object 클래스가 가진 특수 메서드가 호출될 수 있다.

 

예시

예시로 다음의 클래스를 사용하여 __str__ 함수와, __getitem__ 함수를 오버라이딩하여 사용해본다.

 

예시 클래스

class Character():
    def __init__(self):
        self.life = 1000

 

먼저 __str__ 함수와 __getitem__ 함수를 재정의하지 않은 상태로 함수를 실행해 보자.

c = Character()
print(c)
print(c['life'])

print문 사용 시 object 클래스의 __str__ 함수가 호출된 출력문을 확인할 수 있다. 반면 객체의 속성을 딕셔너리처럼 인덱싱 한 경우에는 __getitem__ 함수가 정의되어 있지 않아 에러가 발생한 것을 확인할 수 있다.

 

__str__ 재정의

'Charactor : life={life 값}' 형식의 문자열을 반환하도록 정의한다.

class Character():
    def __init__(self):
        self.life = 1000

    def __str__(self):
        return f'Charactor: life={self.life}'

이제 print 문을 사용하면 object 클래스의 __str__ 함수가 아니라 Charactor 클래스에서 재정의한 __str__ 함수가 호출되어 구현한 문자열 형식으로 출력된 모습을 확인할 수 있다.

 

 

__getitem__ 재정의

Charactor의 속성인 life을 사용해 인덱싱 하면 값을 반환하고, 그 외의 경우에는 AttributeError를 발생하도록 구현했다.

class Character():
    def __init__(self):
        self.life = 1000

    def __getitem__(self, item):
        if item == 'life':
            return self.life
        else:
            raise AttributeError(item)

아래와 같이 인덱싱을 시동하면 Charactor 클래스에서 정의한 __getitem__함수가 호출되어 동작하는 모습을 확인할 수 있다.

c = Character()
print(c['life'])
print(c['test'])

 

 

참고 문서

https://wikidocs.net/84418

https://wikidocs.net/192478

특수 메서드

https://docs.python.org/ko/3/reference/datamodel.html#special-method-names