질문
데코레이트된 메소드와 @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개의 인수만 예상합니다.
a
는 foo
에 바인딩됩니다. "바인딩"이라는 용어는 아래에서 설명됩니다:
print(a.foo)
# <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
a.class_foo
에서는 a
가 class_foo
에 바인딩되지 않습니다. 대신 클래스 A
가 class_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>
댓글