프로그래밍/Python 관련 정보

[Pythonic Programming] Staticmethod/Classmethod

물박사의 저장공간 2024. 10. 27. 17:11

일반적으로 method를 쓸 때 우리는 보통 인스턴스 내부의 변수들을 끌어다 쓰곤 합니다. 

class clexample:
    def __init__(self, input_var):
        self.input_var = input_var
        
    def instance_methd(self):
        print(self.input_var+3)

이런식으로 사용하는 method를 instance method라고 합니다. 말씀드렸다시피 instance 내부에 저장해두었던 정보(instance 속성, instance method 등)를 끌어와서 사용해야할 때는 이런식 방식으로 사용해야겠죠. 그런데, instance나 class속성을 필요로 하지 않거나 혹은 class 속성만 필요로 한다면? 이럴 때는 static method나  class method를 사용해줍니다. 참고로 이 두가지 method는 모두 decorator를 통해서 정의됩니다. (method 위에 @staticmethod, @classmethod와 같은 표기를 해주는 방식입니다)

https://trillionver2.tistory.com/entry/Pythonic-Programming-Decorator

 

[Pythonic Programming] Decorator

함수에 정수나 list 등의 자료형을 넣는 것은 굉장히 익숙하지만.. 함수의 인자로 '함수'가 들어간다면? 직접적으로 함수를 변수로서 담을 수도 있지만 가독성에 문제가 생길 수 있습니다. 이런

trillionver2.tistory.com

 

1. Static method(정적 매서드) : 인스턴스나 클래스에 대한 정보를 전혀 사용하지 않는 method입니다. self나 cls같은 매개변수를 필요로 하지 않으며 단순히 함수처럼 동작하지만 클래스 내부에 존재한다는 점에서 차이가 있습니다. 그냥 함수같은 녀석인데 왜 굳이 클래스 내부에 만들어둘까요? 전에 제가 논리적인 코딩이 '논리적인 글쓰기'와 비슷하다고 말씀드렸던 것 생각 나시나요? 어떤 특정 기능(함수, method 등)이 독립적으로 사용되는 기능이 아니라 특정 클래스의 맥락(context)에서 논리적 선후관계를 가지고 있는 녀석이라면 이것을 그 클래스에 내부에 포함시킴으로써 프로그래밍의 완결성과 통일성을 확보한다고 생각하시면 될 것 같습니다. 사실 기능적인 부분에서만 놓고 보면 그냥 밖으로 함수로 빼서 써도차이가 없는 녀석임에도 굳이굳이 클래스 내부에 기능구현을 시키는 이유입니다. 따라서 static method들은 주로 클래스를 위한 유틸리티 함수를 만들 때 많이 사용합니다. 

class MathUtils:
    @staticmethod
    def add(a, b):
        return a + b

# 정적 메서드는 인스턴스 생성 없이도 클래스 이름으로 호출 가능
result = MathUtils.add(5, 10)
print(result)  # 출력: 15

 

형태적인 차이점도 보이시나요? self라는 매개변수를 인자로 받지않습니다. static method는 클래스의 상태나 인스턴스와 무관하게 동작하기 때문에 받을 이유가 없죠. 

 

2. class method(클래스 메서드) : 클래스 메서드는 클래스 자체에 접근할 수 있는 메서드입니다. 첫 번째 인수로 cls를 받으며, 이를 통해 클래스 (전체에 영향을 미치는 변경을 수행하거나) 클래스를 기반으로 새로운 인스턴스를 생성하는 작업을 수행할 수 있습니다.

class Person:
    population = 0  # 클래스 속성

    def __init__(self, name):
        self.name = name
        Person.population += 1

    @classmethod
    def get_population(cls):
        return cls.population

# 인스턴스를 생성하지 않고 클래스 메서드를 호출할 수 있음
print(Person.get_population())  # 출력: 0

# 인스턴스를 생성하면 population이 증가
p1 = Person("Alice")
p2 = Person("Bob")
print(Person.get_population())  # 출력: 2

 

get_population이라는 class method를 통해 class의 속성에 접근해서 값을 출력하고 있는 것이 보이시나요? p1이나 p2라는 인스턴스를 통해서 출력하는 것이 아니라는 점을 확인해주세요. 

 

instance method와 class method의 차이는 표로 정리하면 다음과 같습니다. 

구분 인스턴스 메서드 클래스 메서드
첫 번째 인수 self (인스턴스) cls (클래스)
호출 시점 인스턴스 생성 후 호출 가능 인스턴스 생성 없이 클래스에서 바로 호출 가능
접근 가능한 속성 인스턴스 속성과 클래스 속성 모두 접근 클래스 속성에만 직접적으로 접근 가능
사용 목적 특정 인스턴스의 상태 조회/변경 클래스 전체에 영향을 주는 변경, 클래스 관련 작업

 

예시를 통해 두 method의 차이를 다시한번 복습해볼까요?

class Car:
    wheels = 4  # 클래스 속성

    def __init__(self, color):
        self.color = color  # 인스턴스 속성

    def change_color(self, new_color):
        self.color = new_color  # 인스턴스 속성 변경

    @classmethod
    def change_wheels(cls, new_wheel_count):
        cls.wheels = new_wheel_count  # 클래스 속성 변경

# 인스턴스 메서드로 인스턴스 속성 변경
car1 = Car("red")
car1.change_color("blue")
print(car1.color)  # 출력: blue (car1의 color만 변경됨)

# 클래스 메서드로 클래스 속성 변경
Car.change_wheels(6)
print(Car.wheels)  # 출력: 6 (모든 Car 인스턴스에 적용됨)
car2 = Car("green")
print(car2.wheels)  # 출력: 6 (새로운 인스턴스에도 적용됨)