언제 @classmethod를 사용해야하고 언제 def method (self)를 사용해야합니까?


88

전에 사용하지 않은 Django 앱을 통합하는 동안 클래스에서 함수를 정의하는 데 사용되는 두 가지 다른 방법을 발견했습니다. 저자는 둘 다 매우 의도적으로 사용하는 것 같습니다. 첫 번째는 내가 많이 사용하는 것입니다.

class Dummy(object):

    def some_function(self,*args,**kwargs):
        do something here
        self is the class instance

다른 하나는 내가 사용하지 않는 것입니다. 주로 사용시기와 용도를 이해하지 못하기 때문입니다.

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        do something here
        cls refers to what?

Python 문서에서 classmethod데코레이터는 다음 문장으로 설명됩니다.

클래스 메서드는 인스턴스 메서드가 인스턴스를받는 것처럼 클래스를 암시 적 첫 번째 인수로받습니다.

그래서 나는 자신을 cls참조한다고 생각 Dummy합니다 ( class인스턴스가 아니라). 나는 항상 이것을 할 수 있기 때문에 이것이 왜 존재하는지 정확히 이해하지 못합니다.

type(self).do_something_with_the_class

이것은 단지 명확성을위한 것일까 요, 아니면 가장 중요한 부분을 놓쳤습니까?

답변:


70

당신의 추측은 정확합니다-당신은 작동 방식 을 이해 합니다classmethod .

그 이유는 이러한 메서드가 인스턴스 또는 클래스 모두에서 호출 될 수 있기 때문입니다 (두 경우 모두 클래스 개체가 첫 번째 인수로 전달됨).

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        print cls

#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()

인스턴스에서 이들의 사용 : 인스턴스에서 클래스 메서드를 호출하는 데 적어도 두 가지 주요 용도가 있습니다.

  1. self.some_function()해당 호출이 발생하는 클래스가 아닌 some_function의 실제 유형에서 의 버전 self을 호출합니다 (클래스 이름이 변경되면주의 할 필요가 없습니다). 과
  2. 경우에 어디에 some_function어떤 프로토콜을 구현하는 것이 필요하다, 그러나 혼자 클래스 객체를에 전화를하는 데 유용합니다.

차이점staticmethod : 인스턴스 데이터에 액세스하지 않는 메서드를 정의하는 또 다른 방법이 staticmethod있습니다. 이는 암시 적 첫 번째 인수를 전혀받지 않는 메서드를 생성합니다. 따라서 호출 된 인스턴스 또는 클래스에 대한 정보가 전달되지 않습니다.

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)

In [7]: Foo.some_static(1)
Out[7]: 2

In [8]: Foo().some_static(1)
Out[8]: 2

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)

In [10]: Bar.some_static(1)
Out[10]: 2

In [11]: Bar().some_static(1)
Out[11]: 2

내가 찾은 주요 용도는 기존 함수 (를받을 것으로 예상하지 않음 self)를 클래스 (또는 객체)의 메서드로 조정하는 것입니다.


2
좋은 것 : 나는 대답이 어떻게-왜인지로 나뉘는 것을 좋아합니다. 지금까지 @classmethod를 사용하면 인스턴스 없이도 함수에 액세스 할 수 있습니다. 이것이 바로 제가 찾던 것입니다. 감사합니다.
marue

1
@marcin 진정한 오리 타이핑은 다른 차원을 제공합니다. 그것은 self.foo()그것이 언제되어야하는 지 와 같은 것을 쓰지 않는 것에 관한 것이었다 Bar.foo().
Voo

5
@Voo 실제로 는 자체를 구현하는 하위 클래스의 인스턴스 일 수 self.foo()있기 때문에 선호 됩니다. selffoo
Marcin

1
@Marcin 나는 이것이 당신이 달성하려는 것에 달려 있다고 생각합니다. 그러나 나는 당신의 요점을 이해합니다.
marue

1
Bar, as에 대해 다른 람다를 사용해야 1+1 == 2 == 1*2하므로 표시된 결과에서 Bar().static_method실제로 호출 되는 것을 알 수 없습니다 .
George V. Reilly

0

기본적으로 메서드 정의가 변경되거나 재정의되지 않을 것임을 알게되면 @classmethod를 사용해야합니다.

추가 : 테오 론적으로 클래스 메서드가 개체 메서드보다 빠릅니다. 인스턴스화 할 필요가없고 메모리가 덜 필요하기 때문입니다.


-3

데코레이터 @classmethod를 추가하면 해당 메서드를 java 또는 C ++의 정적 메서드로 만들 것입니다. (정적 인 방법은 일반적인 용어 I 추측 ) ) 파이썬도 @staticmethod있다. classmethod와 staticmethod의 차이점은 인수 또는 클래스 이름 자체를 사용하여 클래스 또는 정적 변수에 액세스 할 수 있는지 여부입니다.

class TestMethod(object):
    cls_var = 1
    @classmethod
    def class_method(cls):
        cls.cls_var += 1
        print cls.cls_var

    @staticmethod
    def static_method():
        TestMethod.cls_var += 1
        print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()

#construct instances
testMethodInst1 = TestMethod()    
testMethodInst2 = TestMethod()   

#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()

모든 클래스는 cls.cls_var를 1 씩 증가시키고 인쇄합니다.

그리고 동일한 범위에서 동일한 이름을 사용하는 모든 클래스 또는 이러한 클래스로 구성된 인스턴스는 해당 메서드를 공유합니다. TestMethod.cls_var는 하나 뿐이고 TestMethod.class_method (), TestMethod.static_method ()도 하나뿐입니다.

그리고 중요한 질문입니다. 이 방법이 필요한 이유.

classmethod 또는 staticmethod는 해당 클래스를 팩토리로 만들거나 클래스를 한 번만 초기화해야 할 때 유용합니다. 한 번 파일을 열고 피드 방법을 사용하여 한 줄씩 파일을 읽습니다.


2
(a) 정적 메서드는 다른 것입니다. (b) 모든 클래스가 클래스 메소드를 공유하지는 않습니다.
Marcin

@Marcin 내 불분명 한 정의와 모든 것을 알려 주셔서 감사합니다.
Ryan Kim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.