본문 바로가기

Python

Python - Magic Method

이번에는 앞선 클래스에 대해 이해를 돕기 위해서 매직메소드가 무엇인지에 대해 좀 더 알아보겠습니다. 그럼 시작하겠습니다. :)

Magic Method


매직 메소드에 대해서는 앞선 시리즈에서 한번 간단히 소개했던 적이 있다. 그렇지만 정말 간단히 였기에 이번기회에 좀 더 자세히 설명해보려 한다. 이러한 __func__ 형태의 매직메소드는 대부분 파이썬에 내장되어있는 메소드로 각 역할이 있고, 존재 이유가 있다. 실제로 프로그래머가 직접 사용하기보다는 객체에 어떤 액션을 취하느냐에 따라 클래스에서 내부적으로 처리되는 함수들이다. 예를 들자면 __init__ 메소드는 생성자 역할을 하며 클래에스에 인스턴스를 찍어낼 때마다 즉시 실행되는 함수이다.

이해를 돕기 위해 몇가지 예시를 들어가며 설명해보려고 한다.

__str__

우선, 어떤 객체에 대해서 print 문을 찍어본 경험이 있을 것이다. 보면 <function __main__.Robot.cal_add> 와 같이 해당 객체에 대한 설명과 같은 것이 찍히는 것을 확인할 수 있다. 어떻게 이게 가능한 것일까? 이 역할을 해주는 것이 __str__ 이다. print 문에 객체를 넣게 되면 컴퓨터는 사용자에게 해당 객체가 어떤 것인지를 보여주기 위해서 어떻게든 해당 객체를 구겨서 문자열로 바꿔서 보여준다. 이 때 구겨서 문자열로 바꿔주는 것이 __str__ 의 역할이다. 즉 어떤 객체를 print하는 것은 해당 객체에서 __str__ 함수를 실행시킨 것과 동일한 것이다.

print(func)
print(func.__str__

>>> <function func at 0x7f1630954710>
>>> <function func at 0x7f1630954710>

__call__

callable이란 무엇일까? 여기서는 call 호출의 동작을 좀 더 세세히 설명해보고자 한다. 어떤 함수를 실행하고자 할 때 우리는 func() 와 같이 ()를 붙이게 된다. 그렇다면 실행은 어떻게 되는 것일까? 실행은 callable한 객체를 호출한다는 의미를 가지고 있다. callable이란 실행가능하다라는 의미와 동치이다. 

그러면 이를 바탕으로 앞서 정의한 siri 라는 인스턴스 객체를 호출해보자. 아래와 같이 오류가 발생하는 것을 확인할 수 있다. 어째서 이런 오류가 발생하는 것일까? 오류메세지를 살펴보면, 해당 객체가 callable하지 않다고 한다. callable하다는 것은 무엇일까? 파이썬에서 callable을 판단하는 기준은 해당 객체의 namespace에 __call__ 의 존재 유무에 따라서 나뉜다. 즉, siri라는 인스턴스 객체에는 우리가 __call__ 을 정의한 적이 없기에 호출되지 않는 것이다. 따라서 호출되는 객체로 만들고자 한다면 즉 callable한 객체로 만들고자 한다면 우리는 __call__ 이라는 매직메소드를 커스텀해줘야 한다.

siri()

>>> TypeError: 'Robot' object is not callable

매직메소드를 어떻게 커스텀할까? 그건 아래와 같이 해당 객체 클래스 내에서 매직메소드를 정의해주거나 오버라이딩해주면 된다. 예제는 앞서 사용했던 예제를 그대로 가져오겠다. 주목해야할 부분은 아래쪽의 매직메소드를 커스텀하는 부분이다.

class Robot:
    """
    [Robot class]
    Author : 이효석
    Role: test
    """
    
    population = 0 
    
    def __init__(self,name):
        self.name = name
        Robot.population +=1
    
    def say_hi(self):
        # code..
        print(f"Greetings, my masters call me{self.name}.")
        
    def cal_add(self,a,b):
        return a+b
    
    def die(self):
        
        print(f"{self.name}is being destroyed!")
        Robot.population-=1
        if Robot.population ==0:
            print(f"{self.name}was the last one.")
        else:
            print(f"There are still {Robot.population}robots working")
                
    # 클래스 메소드
    @classmethod
    def how_many(cls): 
        print(f"We have {cls.population} robots.")
        
    # staticmethod
    @staticmethod
    def are_you_robot():
        print("yes!!")
        
        
#### 매직메소드 커스텀 #####
    def __str__(self):
        return f"{self.name}robot!!"
    

    def __call__(self):
        print("call!!")
        return f"{self.name} call!!"
        
        
droid1 = Robot("R2-D2")

print(dir(droid1))
>>> ['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'are_you_robot', 'cal_add', 'die', 'how_many', 'name', 'population', 'say_hi']

droid1()
>>> call!!
>>> R2-D2 call!!

이렇게 매직 메소드를 활용해서 호출가능한 callable한 객체로 만들어 줄 수도 있고, print 시 출력되는 string을 우리의 입맛대로 변경해줄 수도 있다. 이 경우 __call__ 이라는 매직메소드를 정의해줌으로써, callable한 객체로 만들어주는 해당 매직 메소드의 역할인 것이다.

추가적으로 두가지 매직 메소드만 더 살펴보겠다. 아주 많은 파이썬의 매직메소드들이 있으니 자세한 것은 해당 링크의 좋은 글을 참고하기 바란다.

 

__doc__

개발자로 협업을 하다보면 클래스의 정보에 대해서 주석을 통해 전달을 하는 경우가 많다. 그 이유는 클래스는 추상화되어 있기 때문에 클래스 안의 로직(복잡한 코드)에 상관없이 input과 output만 잘 적어두면 개발자들이 잘 가져다 쓸 수 있게 설계되어 있기 때문이다. 이러한 주석을 확인할 수 있는 매직메소드가 __doc__ 이며 ''' ''' 혹은 """ """ 를 통해 주석을 달게 된다.

droid1.__doc__
>>> \n    [Robot class]\n    Author : 이효석\n    Role: test\n

__class__

__class__ 같은 경우 어떤 인스턴스에 대해서 해당 인스턴스가 어떤 클래스를 통해 찍힌 것인지를 확인하고자 할 때 사용하게 된다.

droid1.__class__
>>> __main__.Robot

 

더 자세한 내용과 더 많은 매직메소드들에 대한 정보는 Python Refernce를 참고하자.

 

Reference

윤상석 지식제공자 님의 타입 파이썬! 강의내용 : https://www.inflearn.com/course/%ED%83%80%EC%9E%85-%ED%8C%8C%EC%9D%B4%EC%8D%AC

 

타입 파이썬! 올바른 class 사용법과 객체지향 프로그래밍 - 인프런 | 강의

Python으로 생산성있는 개발만 아니라 견고하고 안전하게, 그리고 확장성있는 개발을 하세요! 🔥, - 강의 소개 | 인프런...

www.inflearn.com

 

'Python' 카테고리의 다른 글

Python - Module & Project  (0) 2022.02.15
Python OOP - Part2  (0) 2022.02.13
Python OOP - Part 1 ( Object Oriented Programming)  (0) 2022.02.11
Python - Decorator  (0) 2022.02.02
Python - Variable Length Arguments  (0) 2022.02.02