파이썬 클래스의 코드들을 보면 종종 메서드 위에 데코레이터로 다음과 같은 것들이 붙어있을 때가 있다.
@staticmethod
@classmethod
오늘은 파이썬의 정적 메서드를 만드는 방법인 staticmethod, classmethod에 대해서 알아보도록 하자
본격적인 글에 앞서서 정적메서드(static method)란 무엇일까?
정적 메서드는 클래스가 생성되지 않아도 즉 인스턴스 없이도 사용할 수 있는 함수로 인스턴스에서는 호출 할 수 없는 함수를 가리킨다.
1. staticmethod
staticmethod는 메서드를 정적 메소드로 바꿔주는 것으로 데코레이터를 이용해 바꿔준다.
일반적으로 메서드에는 맨 앞의 argument로 self를 넣어주지만 staticmethod에는 넣어주지 않는다.
class Calculation:
@staticmethod
def add(x,y):
return x + y
Calculation.add(1,3)
하지만 위에서 정의 했다시피 정적 메서드는 인스턴스에서는 접근하지 못해야하지만 아래처럼 가능하다.
원래 자바나 C++에서는 에러가 발생하지만 파이썬에서는 사용가능하다. 유연해서 장점으로 볼 수도 있지만 유연하게 작성한 코드가 발생시키는 복잡성 관점에서 볼 때는 단점으로 볼 수 있을 거 같다.
class Calculation:
@staticmethod
def add(x,y):
return x + y
calc = Calculation()
calc.add(1,3)
2. classmethod
classmethod 역시 메서드를 정적 메서드화 시켜준다. staticmethod와 동일하게 데코레이터 형태로 사용하며 static 메서드와의 차이는 맨 앞의 인자로 클래스 자기자신 cls를 넣어 주어야한다. 한편 classmethod 역시 유연하게 사용가능하다.
class Calculation:
@classmethod
def add(cls,x,y):
return x + y
Calculation.add(1,1)
3. @staticmethod @classmethod 차이
위의 설명에서 staticmethod와 classmethod의 차이가 함수의 첫번째 인자로 cls가 들어간다는 것이였다.
설명만 들으면 이런 생각이 든다. 어쩌라는거지..
이러한 특징은 클래스를 상속해서 사용할 때 유용하게 사용되는데 가령 Dog 클래스를 예를 들어 이야기 해보자
class Dog:
default_country = "한국"
def __init__(self):
self.bark = self.default_country + "개는 왈왈"
@classmethod
def cls_country(cls):
return cls()
@staticmethod
def stat_country():
return Dog()
def make_sound(self):
print(self.bark)
class EnglishDog(Dog):
default_country = "영국"
EnglishDog에서 아래 코드를 실행 시켜보면
stat = EnglishDog.stat_country()
cls = EnglishDog.cls_country()
stat.make_sound()
cls.make_sound()
결과는 아래와 같다
즉 staticclass에서는 Dog() 클래스의 default_country를 사용하지만 classmethod는 cls를 이용해 상속된 class EnglishDog에 접근하는 것을 알 수 있다.
4. 실제 사용 예
파이썬 웹 프레임워크인 장고의 예시를 들고왔다. 장고에서는 model이라는 클래스을 이용해 데이터베이스를 조작하는데 아래와 같이 정의 하면 일련의 과정을 거쳐 데이터베이스에 테이블을 생성한다.
class Item(models.Model):
""" 아이템 모델 정의 """
name = models.CharField(max_length=40)
damage = models.IntergerField()
tier = models.CharField(max_length=20)
cash = models.IntergerField()
description = models.CharField()
이 모델에서 클래스 메서드는 다음과 같이 사용할 수 있다.
class Item(models.Model):
""" 아이템 모델 정의 """
name = models.CharField(max_length=40)
damage = models.IntergerField()
tier = models.CharField(max_length=20)
cash = models.IntergerField()
description = models.CharField()
@classmethod
def get_rare_items(cls) -> QuerySet:
return Item.objects.filter(tier="RARE")
rare_items = Item.get_rare_items()
즉 자주 사용하는 쿼리셋을 클래스 메서드로 구현해서 사용할 수 있다. 물론 비즈니스 로직이 복잡해지면 클래스가 너무 커지기 때문에 manager로 빼서 따로 관리하는 것도 좋은 방법이다. 아래 글은 manager와 클래스 메서드 사이의 찬반의견을 정리해놓은 글이다.
참고 하길 바란다
https://www.b-list.org/weblog/2008/feb/25/managers/
'Language > Python' 카테고리의 다른 글
[Python] Thread-safe 한 자료구조 (0) | 2021.04.29 |
---|---|
[Python] @property 너 누구야? 후아유 (0) | 2021.03.28 |
[Python] pickle 파일 module '__main__' has no attribute 'something' (0) | 2020.11.22 |
[Pipenv] Python 3.7 was not found on your system (0) | 2020.11.19 |
Mac Terminal 에서 conda 안될 때 (0) | 2020.11.17 |