이번 포스팅에서는 파이썬 클래스 문법에서 자주 마주칠 수 있는 staticmethod(정적 메소드)와 classmethod(클래스 메소드)의 차이점에 대해 예시 코드로 알아보려고 한다.
1. staticmethod
우선 staticmethod는 다음과 같은 특징을 지닌다.
- 부모 클래스에서 정의된 staticmethod는 자식 클래스에서 call 할 수 있음
- 클래스 변수에는 접근 가능
- 생성자 포함 인스턴스 메소드 변수에는 접근 불가능
먼저 부모 클래스에서 정의된 staticmethod는 자식 클래스에서 call 할 수 있는 경우이다. 하단의 코드를 살펴보자.
class Parent:
class_val = 'class variable'
def __init__(self):
self.name = 'younghun'
self.age = 27
@staticmethod
def check_name(name):
return name
class Child(Parent):
pass
child = Child()
print(child.check_name('Check name!'))
Child 라는 자식 클래스 객체를 선언하고 부모 클래스인 Parent의 staticmethod를 호출하면 제대로 호출되는 것을 볼 수 있다.
다음은 클래스 변수에는 접근이 가능한 특징이다.
class Parent:
class_val = 'class variable'
def __init__(self):
self.name = 'younghun'
self.age = 27
@staticmethod
def check_name(name):
print(Parent.class_val)
return name
class Child(Parent):
pass
parent = Parent()
print(parent.check_name('Check name!'))
역시 이도 정상대로 동작하는 것을 볼 수 있다.
하지만 인스턴스 메소드에는 접근이 불가능하다.
class Parent:
class_val = 'class variable'
def __init__(self):
self.name = 'younghun'
self.age = 27
@staticmethod
def check_name(name):
print(Parent.class_val)
print(self.name)
return name
class Child(Parent):
pass
parent = Parent()
print(parent.check_name('Check name!'))
2. classmethod
다음은 클래스 메소드의 특징들이다
- 부모 클래스에서 정의된 클래스 변수와 클래스 메소드는 자식 클래스에서도 선언이 가능
- 클래스 변수에 접근이 가능
- 생성자 함수 포함 인스턴스 메소드 변수에 접근이 불가능
staticmethod와 특징이 비슷하다. 먼저 첫 번째 특징인 부모 클래스에서 정의된 클래스 변수와 클래스 메소드는 자식 클래스에서도 선언이 가능한 것이 특징이다.
class Parent:
class_val = 'class variable'
def __init__(self):
self.name = 'younghun'
self.age = 27
@classmethod
def change_class_val(cls, other_val):
cls.class_val = other_val
return cls.class_val
class Child(Parent):
print(Parent.class_val)
pass
# 부모 클래스에서 호출 가능
parent = Parent()
print(parent.change_class_val('other class variable!'))
# 자식 클래스에서 호출 가능
child = Child()
print(child.change_class_val('other class variable!'))
두번째 특징인 클래스 변수에 접근이 가능한 점은 클래스 메소드의 본질적인 특징이므로 따로 설명은 안하겠다. 마지막 인스턴스 메소드 변수에 대한 접근이 불가능한 특징이다.
class Parent:
class_val = 'class variable'
def __init__(self):
self.name = 'younghun'
self.age = 27
@classmethod
def change_class_val(cls, other_val):
cls.class_val = other_val
print(cls.class_val)
print(self.name)
return cls.class_val
class Child(Parent):
pass
parent = Parent()
print(parent.change_class_val('otehr class variable!'))
3. staticmethod VS classmethod
두 개의 차이점은 클래스 상속할 때 나뉜다. 우선 staticmethod 는 부모클래스에서 호출하던 자식클래스에서 호출하던 클래스 변수를 모두 바꿀 수 있다. 다음의 코드를 보자.
class Parent:
name = 'Younghun Jo'
@staticmethod
def change_name(new_name):
Parent.name = new_name
class Child(Parent):
pass
parent = Parent()
child = Child()
parent.change_name('Heungmin Son')
print('부모 클래스에서 선언할 때:\n', parent.name, child.name)
print('-'*50)
child.change_name('Jisung Park')
print('자식 클래스에서 선언할 때:\n', parent.name, child.name)
결과화면은 다음과 같다. 클래스 변수인 name이 모두 손흥민, 박지성으로 바뀐 것을 볼 수 있다.
그러나 classmethod로 선언할 때는 어떻게 결과화면이 바뀌는지 보자.
class Parent:
name = 'Younghun Jo'
@classmethod
def change_name(cls, new_name):
cls.name = new_name
class Child(Parent):
pass
parent = Parent()
child = Child()
parent.change_name('Heungmin Son')
print('부모 클래스에서 선언할 때:\n', parent.name, child.name)
print('-'*50)
child.change_name('Jisung Park')
print('자식 클래스에서 선언할 때:\n', parent.name, child.name)
부모 클래스 객체로 선언할 때는 부모, 자식 클래스 변수 모두 손흥민으로 바뀌었지만 자식 클래스 객체로 선언할 때는 자식 클래스의 클래스 변수만 박지성으로 바뀌고 부모 클래스의 변수는 바뀌지 않은 것을 볼 수 있다. 물론 위 경우는 반드시 부모 클래스에서 호출한 뒤에 자식 클래스에서 호출할 때만 발생하는 현상이다. 만약에 부모클래스에서 먼저 호출하지 않고 애초에 처음부터 자식 클래스에서 클래스 메소드를 호출하면 부모 클래스, 자식 클래스의 변수 모두 갱신이 가능하다.(또한 자식 클래스에서 부모 클래스의 클래스 변수를 오버라이딩 하지 않았을 경우에만이라는 점도 알아두자)
결과적으로, staticmethod는 부모, 자식 클래스 어디에서 선언하든 클래스 변수를 모두 바꾸지만 classmethod에서는 부모 클래스 객체에서 선언해야만 자식 클래스의 클래스 변수까지 모두 바꿀 수 있다. 만약 classmethod를 사용하는데 자식 클래스 객체에서 선언하게 된다면 부모 클래스의 클래스 변수는 그대로이고 자식 클래스의 클래스 변수만 바뀌는 것이다.
'Python > Python' 카테고리의 다른 글
[Python] yield를 사용하는 제네레이터와 itertools의 다양한 함수들 (0) | 2021.10.17 |
---|---|
[Python] iterator 와 generator에 대해 알아보기 (0) | 2021.10.16 |
[Python] Class 에서 return self 는 무엇을 의미할까? (0) | 2021.08.26 |
[Python] yield로 제네레이터 함수 만들기 (0) | 2021.08.25 |
[Python] 클래스 상속 시 super() 의 쓰임 (0) | 2021.08.25 |