[Python] 25. 클래스 메소드와 static 메소드
본 포스팅은 “윤성우의 열혈 파이썬 중급편” 책 내용을 기반으로 작성되었습니다. 잘못된 내용이 있을 경우 지적해 주시면 감사드리겠습니다.
25-1. 클래스 변수에 대한 이해
class Simple:
def __init__(self):
self.iv = 10 # iv는 인스턴스 변수(첫 대입 연산에서 생성되는 변수로써 객체별로 존재)
s = Simple()
s.iv # 인스턴스 변수는 개게 통해 접근!
(결과) 10
class Simple:
cv = 20 # 클래스 변수! 클래스 Simple에 속하는 변수임
def __init__(self):
self.iv = 10
Simple.cv # 클래스 변수는 클래스 이름으로 접근 가능!
s = Simple()
s.cv # 클래스 변수는 객체를 통해서도 접근 가능!
s.iv
(결과) 20
20
10
클래스 변수는 인스턴스 변수랑 헷갈려보일 수 있음! 따라서 클래스 이름을 통해 접근하는 것을 권함
class Simple:
count = 0
def __init__(self):
Simple.count += 1 # 클래스 내에서 클래스 변수에 접근하는 방법
def get_count(self):
return Simple.count
def main():
s1 = Simple()
print(s1.get_count())
s2 = Simple()
print(s1.get_count())
s3 = Simple()
print(s1.get_count())
main()
(결과) 1 2 3
25-2. static 메소드
바로 위 예제에서 get_count 메소드를 호출하려면 객체가 있어야 한다.
static 메소드는 클래스에 속하는 메소드로, 객체 생성 없이 호출이 가능하다는 장점이 있다. 클래스 변수와 상당히 유사하다.
class Simple:
def sm():
print('static method')
sm = staticmethod(sm) # sm 메소드를 static 메소드로 만드는 방법!
def main():
Simple.sm() # static 메소드는 클래스 이름 통해 호출 가능하다!
s = Simple()
s.sm() # static 메소드는 객체를 통해서도 호출 가능하다!
main()
(결과) static method
static method
static 메소드와 인스턴스 메소드 차이는 첫번째 인자로 self를 전달 받지 못하냐, 받을 수 있냐에 있다.
클래스에 속한 메소드이니 당연히 self를 인자로 전달 받지 못한다.
위 예제의 코드를 보면 뭔가 떠오르는게 있지 않는가? sm = staticmethod(sm)
바로 전에 데코레이터에서 봤다!
class Simple:
count = 0
def __init__(self):
Simple.count += 1
@staticmethod
def get_count(): # 매개변수 self가 없는 static 메소드 선언!
return Simple.count
def main():
print(Simple.get_count())
s = Simple()
print(Simple.get_count())
main()
(결과) 0
1
25-3. class 메소드
class Simple:
num = 5
@staticmethod # static 메소드 만들기 위한 데코레이터
def sm(i):
print('st~ 5 + {0} = {1}'.format(i, Simple.num+i))
@classmethod # class 메소드 만들기 위한 데코레이터
def cm(cls, i): # cls만 빼면 static 메소드와 동일!
print('cl~ 5 + {0} = {1}'.format(i, Simple.num+i))
def main():
Simple.sm(3)
Simple.cm(3)
s = Simple()
s.sm(4)
s.cm(4)
main()
(결과) st~ 5 + 3 = 8
cl~ 5 + 3 = 8
st~ 5 + 4 = 9
cl~ 5 + 4 = 9
class 메소드는 cls인자를 갖는다는 것만 빼면 static 메소드와 동일하다. 그럼 cls 인자는 무엇을 의미할까?
class Simple:
count = 0
def __init__(self):
Simple.count += 1
@classmethod
def get_count(cls):
return cls.count
def main():
print(Simple.get_count()) # get_count의 cls에 전달되는 것은 Simple 클래스!
s = Simple()
print(Simple.get_count())
main()
(결과) 0
1
보다시피 cls에 전달되는 것은 Simple 클래스이다!
즉, return cls.count가 return Simple.count가 되는 것이다!
다음처럼 클래스 메소드를 이용하여 객체를 생성할 수도 있다.
class Natural:
def __init__(self, n):
self.n = n
def getn(self):
return self.n
@classmethod
def add(cls, n1, n2):
return cls(n1.getn() + n2.getn())
def main():
n1 = Natural(1)
n2 = Natural(2)
n3 = Natural.add(n1, n2)
print('{0} + {1} = {2}'.format(n1.getn(), n2.getn(), n3.getn()))
main()
(결과) 1 + 2 = 3
25-4. static 메소드보다 class 메소드가 더 어울리는 경우
class Date:
def __init__(self, y, m, d):
self.y = y
self.m = m
self.d = d
def show(self):
print('{0}, {1}, {2}'.format(self.y, self.m, self.d))
@classmethod
def next_day(cls, today):
return cls(today.y, today.m, today.d + 1)
def main():
d1 = Date(2025, 4, 5)
d1.show()
d2 = Date.next_day(d1)
d2.show()
main()
(결과) 2025, 4, 5
2025, 4, 6
위 예제에서 next_day 메소드는 새로운 객체 생성 및 반환하는 역할을 한다. 이러한 메소드를 ‘팩토리 메소드’라 한다. 클래스 메소드는 클래스 정보가 전달이 되기 때문에, 팩토리 메소드를 만드는데 매우 적합하다!
25-5. static 메소드보다 class 메소드가 완전 더 어울리는 경우
class Date:
def __init__(self, y, m, d):
self.y = y
self.m = m
self.d = d
def show(self):
print('{0}, {1}, {2}'.format(self.y, self.m, self.d))
@classmethod
def next_day(cls, today):
return cls(today.y, today.m, today.d + 1) # static 메소드로 구현하려 했다면, 조건문으로 두 개 만들어야...
class KDate(Date):
def show(self):
print('KOR: {0}, {1}, {2}'.format(self.y, self.m, self.d))
class JDate(Date):
def show(self):
print('JPN: {0}, {1}, {2}'.format(self.y, self.m, self.d))
def main():
kd1 = KDate(2025, 4, 12)
kd1.show()
kd2 = KDate.next_day(kd1) # KDate가 cls로 넘어감
kd2.show()
jd1 = JDate(2027, 5, 19)
jd1.show()
jd2 = JDate.next_day(jd1) # JDate가 cls로 넘어감
jd2.show()
main()
(결과) KOR: 2025, 4, 12
KOR: 2025, 4, 13
JPN: 2027, 5, 19
JPN: 2027, 5, 20
Leave a comment