본문 바로가기
Python/Python FAQ

Python @staticmethod와 @classmethod의 차이점, Difference between @staticmethod and @classmethod

by 베타코드 2023. 5. 4.
반응형

질문

 

데코레이트된 메소드와 @staticmethod로 데코레이트된 메소드, 그리고 @classmethod로 데코레이트된 메소드의 차이점은 무엇인가요?

 

답변

 

아래의 예제 코드를 보면서 이해해보세요: foo, class_foo, static_foo의 호출 시그니처의 차이점을 주목하세요:

class A(object):
    def foo(self, x):
        print(f"executing foo({self}, {x})")

    @classmethod
    def class_foo(cls, x):
        print(f"executing class_foo({cls}, {x})")

    @staticmethod
    def static_foo(x):
        print(f"executing static_foo({x})")

a = A()

아래는 객체 인스턴스가 메서드를 호출하는 일반적인 방법입니다. 객체 인스턴스인 a가 암시적으로 첫 번째 인수로 전달됩니다.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>, 1)

클래스 메서드에서 객체 인스턴스의 클래스가 self 대신 암시적으로 첫 번째 인수로 전달됩니다.

a.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

클래스 메서드로 정의하는 경우 클래스 인스턴스 대신 클래스에서 호출할 것을 의도했기 때문에 클래스에서 class_foo를 호출할 수도 있습니다. A.foo(1)은 TypeError가 발생하지만 A.class_foo(1)는 문제없이 작동합니다:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>, 1)

사람들이 클래스 메서드를 사용하는 한 가지 방법은 상속 가능한 대안 생성자를 만드는 것입니다.


정적 메서드에서는 self (객체 인스턴스)나 cls (클래스)가 암시적으로 첫 번째 인수로 전달되지 않습니다. 그들은 일반 함수처럼 동작하지만 인스턴스나 클래스에서 호출할 수 있습니다:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

정적 메서드는 클래스와 논리적으로 관련된 함수를 클래스에 그룹화하는 데 사용됩니다.


foo는 그냥 함수이지만, a.foo를 호출하면 함수가 아닌 함수의 첫 번째 인수로 객체 인스턴스 a가 바인딩된 "부분적으로 적용된" 버전의 함수를 얻게 됩니다. foo는 2개의 인수를 예상하지만, a.foo는 1개의 인수만 예상합니다.

afoo에 바인딩됩니다. "바인딩"이라는 용어는 아래에서 설명됩니다:

print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>

a.class_foo에서는 aclass_foo에 바인딩되지 않습니다. 대신 클래스 Aclass_foo에 바인딩됩니다.

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

여기서 정적 메서드로, 메서드이지만, a.static_foo는 인수가 바인딩되지 않은 일반 함수만 반환합니다. static_foo는 1개의 인수를 예상하며, a.static_foo도 1개의 인수를 예상합니다.

print(a.static_foo)
# <function static_foo at 0xb7d479cc>

물론 클래스 A를 사용하여 static_foo를 호출할 때도 같은 일이 발생합니다.

print(A.static_foo)
# <function static_foo at 0xb7d479cc>
반응형

댓글