3 분 소요

classmethod & staticmethod

클래스 선언 부에서 확인할 수 있는 @classmethod@staticmethod에 대해서 알아보자.

두 데코레이터 모두 정적 메소드를 의미하며, 정적 메소드란 인스턴스를 생성하지 않고 호출 할 수 있는 메소드를 의미한다.

우선 본격적인 학습 전에 클래스의 변수에 대해 짧은 코드로 확인해보자.

class class1 :
    temp = 10 # 클래스 변수
    def __init__ (self, A, B): # 생성자 
        self.A=A # 인스턴스 변수
        self.B=B # 인스턴스 변수

클래스 변수

클래스 메소드를 확인하기 전에 모든 직원에게 똑같이 시급을 주는 이상한 술집의 직원을 객체화 해보자.

#work.py

class employee:
    def __init__(self,name,time,hourlywage):
        self.name=name
        self.time=time
        self.hourlywage=hourlywage

    def wage(self):
        wage=self.time * self.hourlywage
        print(f"{self.name}님의 이번 달 근무 시간은 {self.time}시간이며, 예상 급여는 {wage}원 입니다.")

생성자를 통해 이름, 한 달 간 근무시간, 시급을 멤버 변수로 갖는 인스턴스를 생성할 수 있다.

wage 함수를 통해 인스턴스별 한달 예상 급여를 알 수 있다.

import work

employee1 = work.employee('윤정호',145,8600)
employee2 = work.employee('드와이트',123,8600)
employee3 = work.employee('마이클',110,8600)

employee1.wage()
employee2.wage()
employee3.wage()

윤정호님의 이번 달 근무 시간은 145시간이며, 예상 급여는 1247000원 입니다. 드와이트님의 이번 달 근무 시간은 123시간이며, 예상 급여는 1057800원 입니다. 마이클님의 이번 달 근무 시간은 110시간이며, 예상 급여는 946000원 입니다.

여기서 만약 가게가 잘 돼서 시급이 400원 오른 9000원 으로 변경 되었다고 생각해보자.

그렇다면 객체를 생성하는 코드를 전부 변경해주어야한다.

.
.
employee1 = work.employee('윤정호',145,9000)
employee2 = work.employee('드와이트',123,9000)
employee3 = work.employee('마이클',110,9000)
.
.

지금이야 직원이 3명이지만 해당 객체가 많아질수록 효율성은 떨어지게 된다.

이럴 땐 클래스 변수를 사용하면 해결된다.

#work.py

class employee:
    hourlywage=8600
    
    def __init__(self,name,time):
        self.name=name
        self.time=time
        #self.hourlywage=hourlywage

    def wage(self):
        wage=self.time * self.hourlywage
        print(f"{self.name}님의 이번 달 근무 시간은 {self.time}시간이며, 예상 급여는 {wage}원 입니다.")
import work

employee1 = work.employee('윤정호',145)
employee2 = work.employee('드와이트',123)
employee3 = work.employee('마이클',110)

employee1.wage()
employee2.wage()
employee3.wage()

print("-------임금 인상-------")
work.employee.hourlywage = 9000

employee1.wage()
employee2.wage()
employee3.wage()

윤정호님의 이번 달 근무 시간은 145시간이며, 예상 급여는 1247000원 입니다. 드와이트님의 이번 달 근무 시간은 123시간이며, 예상 급여는 1057800원 입니다. 마이클님의 이번 달 근무 시간은 110시간이며, 예상 급여는 946000원 입니다. ——-임금 인상—— 윤정호님의 이번 달 근무 시간은 145시간이며, 예상 급여는 1305000원 입니다. 드와이트님의 이번 달 근무 시간은 123시간이며, 예상 급여는 1107000원 입니다. 마이클님의 이번 달 근무 시간은 110시간이며, 예상 급여는 990000원 입니다.

이상태에서 시급에 변수에 대해서 클래스가 아니라 인스턴스로 접근하면 어떻게 될까 ?

.
.
.# 윗 부분 생략
print("-------임금 인상-------")
work.employee.hourlywage = 9000

employee1.hourlywage= 10000

employee1.wage()
employee2.wage()
employee3.wage()

——-임금 인상——- 윤정호님의 이번 달 근무 시간은 145시간이며, 예상 급여는 1450000원 입니다. 드와이트님의 이번 달 근무 시간은 123시간이며, 예상 급여는 1107000원 입니다. 마이클님의 이번 달 근무 시간은 110시간이며, 예상 급여는 990000원 입니다.

생성자를 통해 인스턴스 변수를 초기화 해준 적이 없음에도 인스턴스 변수가 생성되어 클래스 변수가 아닌 인스턴스 변수로 함수가 동작한다.

이런 경우를 위해 클래스 메소드를 사용할 수 있다.

@classmethod

@classmethod 데코레이터를 통해 클래스 함수를 지정해줄 수 있다.

인자로 ‘cls’ 가 필수로 존재하며, 이는 클래스 그 자체를 의미한다.

class employee:
.
.#(중략)
.

    @classmethod
    def set_hourlywage(cls,N):
        cls.hourlywage=N
.

set_hourlywage 함수를 추가해줬다.

이제 해당 함수를 사용해보자.

.
.
.# 윗 부분 생략
print("-------임금 인상-------")
work.employee.hourlywage = 9000

employee1.set_hourlywage(10000)

employee1.wage()
employee2.wage()
employee3.wage()

——-임금 인상——- 윤정호님의 이번 달 근무 시간은 145시간이며, 예상 급여는 1450000원 입니다. 드와이트님의 이번 달 근무 시간은 123시간이며, 예상 급여는 1230000원 입니다. 마이클님의 이번 달 근무 시간은 110시간이며, 예상 급여는 1100000원 입니다.

짜잔~! 클래스에 직접 접근하지 않고 인스턴스를 통해 접근했음에도 클래스 메소드를 통해 클래스 변수의 값을 변경하였다.

사실 이 부분만으론 굳이 왜 이렇게 하지 싶은 의문이 들 수 밖에 없다.

그 의문은 언젠간 작성할 캡슐화(은닉화)을 통해 해결할 수 있다.

@staticmethod

이번엔 staticmethod에 대해서 알아보자.

@staticmethod는 첫 번째 매개변수가 필요하지 않도록 하는 데코레이터이다.

클래스 메소드는 cls를 매개변수로 필요했고 인스턴스 메소드는 self를 필요로 한 것과 차이가 난다.

코드를 통해 알아보자

# work.py
class employee:
    .
    .
    .#   (중략)
	@staticmethod
    def clac(self,x,y):
        return x*y

if __name__ == '__main__' :    
	a = employee.clac(2,4)
    print(a)   

TypeError: clac() missing 1 required positional argument: ‘y’

에러 코드를 통해 볼 수 있듯이 @staticmethod 는 self를 하나의 인자로서 인수를 요구한다.

self = 2, x=4 가 되므로 y 인자에 어떤 인수도 들어가지 않게 된다.

@staticmethod 데코레이터를 사용할 땐 절대 self나 cls를 인자로 가질 수 없다.

@statiemethod 는 내 짧은 식견으론 클래스를 객체화가 아닌 모듈화를 하여 사용할 때 말고는 크게 사용할 일은 없을 것 같다.

댓글남기기