지식이 늘었다/웹개발

Python의 @classmethod, @staticmethod, 데코레이터 @

PurpleGuy101 2024. 12. 17. 10:03

 

0.

 

특정 인스턴스의 메소드를 수행하려고 한다면 어떻게 해야하는가?

 

class ClassTest:
    def instance_method(self):
        print(f"Called instance_method of {self}")

#1
test = ClassTest()
test.instance_method()
ClassTest.instance_method(test)

#Called instance_method of <__main__.ClassTest object at 0x0000018D8BFF0370>

 

test 인스턴스를 찍어낸뒤

test.instance_method()로 메소드를 수행할 수도 있고

ClassTest.instance_method(test)처럼 클래스에서 메소드를 호출하고

test인스턴스를 전달해줘도 된다.

 

그렇기 때문에 인스턴스의 메소드는

객체Object가 필요하다.

 

(객체=Python에서 생성된 모든 데이터와 메서드의 집합.

클래스에서 생선된 모든 것, 정수,문자열, 리스트, 함수, 클래스, 클래스그자체도 객체임)

(인스턴스=특정 클래스를 기반으로 생성된 객체, 클래스의 실체화.

이 경우 ClassTest 클래스를 토대로 찍어낸 객)

 

1.

 

특정'인스턴스'의 메소드를 실행하면서 인스턴스의 메소드를 알아보았다.

 

그리고 이번엔 특정'클래스'의 메소드에 대해서도 알아보자.

@classmethod 를 입력하고

그 밑에 해당 클래스를 파라미터로 전달해주는 

def class_method(cls)를 정의해준다.

 

인스턴스의 self처럼

해당 클래스 자체를 의미하는 cls를 통과시켜준다.

class ClassTest:
    def instance_method(self):
        print(f"Called instance_method of {self}")

    @classmethod
    def class_method(cls):
        print(f"Called class_method of {cls}")
    

#2
ClassTest.class_method() # Python will pass ClassTest automaticallly
# Output : Called class_method of <class '__main__.ClassTest'>

 

위와 같이 인스턴스를 전달해주지 않아도 작동하는 것을 볼 수 있다.

이 클래스메소드를 어디에 쓰는지는 뒤에서 자세히 알아보겠지만

클래스 상태를 다룰 때 사용된다.

 

2.

 

마지막으로

@staticmethod이다.

얘는 애초에 클래스와 관련된 메소드라고 보기도 힘든게, 객체의 상태에 대한 설명을 하지도 않는다.

class ClassTest:
    def instance_method_example(self):
        print(f"Called instance_method of {self}")

    @classmethod
    def class_method_example(cls):
        print(f"Called class_method of {cls}")

    @staticmethod
    def static_method_example():
        print("Called static_method.")
    

#
ClassTest.static_method_example()
# Output : Called static_method.

 

클래스나 인스턴스와 관계없이 독립적으로 동작하는 메서드를 정의할때 사용된다.

역시 인스턴스 없이 호출가능하며

클래스의 네임스페이스에 속한다.

 

3.

 

이러한 @classmethod와 @staticmethod는 데코레이터이다.

많은 클래스의 경우, 생성할 인스턴스에 관한 내용을 정의하지만

@classmethod와 @staticmethod는 클래스 자체와 관련된 메서드를 만들때 사용된다.

 

이러한 클래스메소드와 스태틱메소드라는 데코레이터를 통해서

기존코드를 수정하지 않고도 새로운 기능을 추가할 수 있게 된다.

 

4.

객체지향의 Open-Close Principle와 매우 관련이 많은 녀석이다..

정보처리기사에서 디자인팬턴 암기하면서 

ABCDFFP 이렇게 외웠을때 끼여있던 D의 Decorator인데

객체에 동적으로 새로운 기능을 추가하여 객체를 확장할 수 있는 패턴이다..

 

5.

감이 안오는게 당연하다. 예시를 보면서 헤딩하는게 나을거 같으니 

Class Method를 이용해서

Factory Example을 만들어보자.

 

class Book:
    TYPES = ("hardcover", "paperback")

    def __init__(self, name, book_type, weight):
        self.name = name
        self.book_type = book_type
        self.weight = weight
    
    def __repr__(self):
        return f"<Book {self.name}, {self.book_type}, weighing {self.weight}g>"

    @classmethod
    def hardcover(cls, name, page_weight):
        return Book(name, Book.TYPES[0], page_weight +100)
        
    @classmethod
    def paperbook(cls, name, page_weight):
        return Book(name, Book.TYPES[1], page_weight)
        

book1 = Book("Harry Potter","comic book" ,1500)
print(book1) 
# Output : <Book Harry Potter, comic book, weighing 1500g>


book2 = Book.hardcover("Harry Potter", 1500)
print(book2)
# Output : <Book Harry Potter, hardcover, weighing 1600g>

 

기존의 클래스에서 인스턴스를 생성할 때에는 

__init__ 메소드를 통해서 name, book_type, weight 3개의 입력값을 전달해줘야 하였다.

 

@classmethod로 선언한 

hardcover나 paperbook이라는 클래스메소드에서는 book 인스턴스를 따로 생성후 전달할 필요도 없으며

미리 정해진 Book.TYPES를 통해서 cls와 name, weight 2개의 입력값만을 아규먼트로 전달해서

인스턴스를 생성해줄 수 있다.

 

이러한 방식의 Factory Method는 매우 많이 쓰이는 방법이며

클래스의 상속Inheritance 과정에서 핵심역할을 한다.

 

6.

클래스를 꾸며주는 데코레이터 @에 대한 문법을 알아보았다.

위의 두 @classmethod 와 @staticmethod뿐만아니라

 

직접 데코레이터를 커스텀할 수 있는데,

아래와 같이 기존 함수나 메소드의 변형없이 함수를 꾸며주는 기능을 수행하는 것을 확인할 수 있다.

 

def my_decorator(func):
    def wrapper():
        print("함수를 호출하기 전에 실행됩니다.")
        func()
        print("함수를 호출한 후에 실행됩니다.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

# 출력
# 함수를 호출하기 전에 실행됩니다.
# Hello!
# 함수를 호출한 후에 실행됩니다.

 

 

7.

요약

@ decorator는

파이썬에서 함수나 메서드에 기능을 추가하거나 수정할 때 사용하는 도구이다.

'지식이 늘었다 > 웹개발' 카테고리의 다른 글

Python의 Import와 __name__, relative import  (0) 2024.12.17
Python 문법 Type Hinting  (0) 2024.12.17
Python의 Magic Method - __repr__()와 __str__()  (1) 2024.12.16
Python의 *, ** 문법  (0) 2024.12.16
API와 REST API  (0) 2024.12.12