파이썬 코드를 보다 보면 클래스 정의 부분에 __init__(), __str__(), __add__() 와 같은 메소드를 보시곤 했을 것입니다. __init__()은 생성자로 객체를 생성할 때 처리할 내용을 작성하기 위한 함수로서, 많이 보셨을 것입니다.
그런데 그 외에 다른 __로 시작하고 __로 끝나는 메소드들이 클래스 안에 들어가 있으면 왠지 모르게 어렵게 느껴집니다. 하지만, 그것들의 존재 이유를 알고 나면 오히려 굉장히 유용한 메소드들이라는 사실에 반가운 마음이 들 것입니다. 이 메소드들을 매직 메소드라고 부릅니다. 특별한 이름을 가지고 있고 마법과 같은 일을 수행하기 때문에 그러한 이름이 붙은 것 같습니다.
오늘은 몇 가지 매직 메소드를 직접 구현해보면서 이들과 친해지는 시간을 가져보도록 하겠습니다.
자주 쓰이는 매직 메소드
__str__()
class Player:
def __init__(self, name: str, goal: int):
self.name = name
self.goal = goal
p1 = Player('손흥민', 23)
print(p1)
위와 같이 Player 객체를 하나 생성한 후 print 해보면 이 데이터가 존재하는 주소만 나올뿐 데이터에 대한 내용은 볼 수 없습니다. 그런데 print 했을 때 내용이 나오면 좋겠죠? 이런 경우에 __str__() 메소드를 정의해주면 됩니다.
class Player:
def __init__(self, name: str, goal: int):
self.name = name
self.goal = goal
def __str__(self):
return f'Player(name={self.name}, goal={self.goal})'
p1 = Player('손흥민', 23)
print(p1)
이렇게 print 해줬을 때 데이터 내용이 나오는 것이 주소가 나오는 것보다 훨씬 정보성이 있기 때문에 __str__() 메소드를 많이 사용합니다.
__lt__(), __le__(), __eq__(), __ne__(), __gt__(), __ge()
위 메소드들은 두 객체를 비교할 때 사용됩니다.
class Player:
def __init__(self, name: str, goal: int):
self.name = name
self.goal = goal
def __str__(self):
return f'Player(name={self.name}, goal={self.goal})'
def __lt__(self, other):
return self.goal < other.goal
def __ge__(self, other):
return self.goal >= other.goal
def __eq__(self, other):
return self.goal == other.goal
p1 = Player('손흥민', 23)
p2 = Player('황희찬', 15)
print(p1 < p2)
print(p1 >= p2)
print(p1 == p2)
보시다시피 <, >=, == 연산자 등이 우리가 원하는 기능을 하도록 만들어줄 수 있습니다. 저는 각 객체의 골 수로 크기를 비교하도록 했습니다. __lt__()는 <, __le__()는 <=, __eq__()는 ==, __ne__()는 !=, __gt__()는 >, __ge__()는 >=와 매치됩니다.
__add__(), __sub__(), __mul__(), __truediv__(), __mod__(), __pow__()
+, -, *, /, % 연산자도 우리가 원하는 기능을 수행하도록 해줄 수 있습니다.
class Player:
def __init__(self, name: str, goal: int):
self.name = name
self.goal = goal
def __str__(self):
return f'Player(name={self.name}, goal={self.goal})'
def __lt__(self, other):
return self.goal < other.goal
def __ge__(self, other):
return self.goal >= other.goal
def __eq__(self, other):
return self.goal == other.goal
def __add__(self, other):
return self.goal + other.goal
def __sub__(self, other):
return self.goal - other.goal
p1 = Player('손흥민', 23)
p2 = Player('황희찬', 15)
print(p1 + p2)
print(p1 - p2)
__add__() 메소드를 활용하여 두 객체의 골 수를 + 연산자를 통해 더할 수 있게 해봤습니다. 또한 __sub__() 메소드를 활용하여 두 객체의 골 수를 - 연산자를 통해 뺄 수 있게 해봤습니다.
__call__()
인스턴스가 함수처럼 호출될 때 호출되는 메소드입니다.
class Player:
def __init__(self, name: str, goal: int):
self.name = name
self.goal = goal
def __str__(self):
return f'Player(name={self.name}, goal={self.goal})'
def __lt__(self, other):
return self.goal < other.goal
def __ge__(self, other):
return self.goal >= other.goal
def __eq__(self, other):
return self.goal == other.goal
def __add__(self, other):
return self.goal + other.goal
def __sub__(self, other):
return self.goal - other.goal
def __call__(self):
print(f"{self.name} 인스턴스를 함수처럼 호출하셨습니다.")
p1 = Player('손흥민', 23)
p2 = Player('황희찬', 15)
p1()
p2()
위 코드를 보시면 신기하게 p1, p2 인스턴스에 ()를 붙여주니 __call__() 메소드가 호출되었습니다.
정리하며
이제 파이썬 코드에서 __메소드__()를 만나도 두렵지 않으시겠죠? 뭔가 특별한 기능을 수행하는 매직 메소드일 뿐입니다. 이 관점만 가지고 코드를 보아도 훨씬 코드 파악이 쉬워지실 것입니다.
참고자료
[1] https://docs.python.org/ko/3.7/reference/datamodel.html#special-method-names
[2] https://www.tutorialsteacher.com/python/magic-methods-in-python
'Dev > python' 카테고리의 다른 글
[python] 클래스 속성과 클래스 메서드 (0) | 2023.01.28 |
---|---|
[python] 정적 메서드(static method)는 주로 어떤 경우에 사용되는가 (0) | 2023.01.27 |
[python] 비공개 속성, 게터, 세터, @property (0) | 2023.01.26 |
[python] 약수 구하는 알고리즘 (0) | 2023.01.26 |
[python] 제너레이터의 필요성(메모리 효율성) (0) | 2023.01.16 |
[pandas] 데이터프레임의 행들을 반복문에서 얻고 싶다면, df.iterrows() (0) | 2023.01.14 |
[python] *args, **kwargs란? (0) | 2023.01.13 |
[python] 두 개의 리스트를 동시에 이터레이션하려면 zip 함수 사용 (0) | 2023.01.13 |