50

전에 사용하지 않은 Django 앱을 통합하는 동안 클래스에서 함수를 정의하는 데 두 가지 다른 방법이 사용되었습니다. 저자는 둘 다 매우 의도적으로 사용하는 것 같습니다. 첫 번째는 하나가 나 자신이 많이 사용됩니다언제 @classmethod를 사용해야하고 def 메소드 (자체)를 사용해야합니까?

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? 

파이썬 문서에서 classmethod 장식이 문장을 설명한다 :

클래스 메소드는 인스턴스 메소드 인스턴스를 수신 다만 같이 암시 첫번째 인자로 클래스를 수신한다.

그래서 나는 cls합니다 (class 인스턴스가 아니라) 자체 Dummy을 의미 같아요. 나는 정확히이 존재 왜 항상이 할 수 있기 때문에, 이해가 안 :

type(self).do_something_with_the_class 

단지 명확성을 위해이, 아니면 내가 가장 중요한 부분을 그리워했다 : 수 없었다 유령 매혹적인 것들 그것없이 끝났습니까?

답변

47

귀하의 추측은 정확합니다. 은 어떻게 생각합니까?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()self의 실제 유형에 some_function의 버전을 호출보다는 제공자 라이선스 계약 : 인스턴스에 classmethod를 호출 적어도 두 가지 용도가있다 그 호출이 발생합니다 (클래스 이름이 바뀌면주의를 기울일 필요가 없습니다).
  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 

내가 그것을 발견 한 주요 용도는 클래스 (또는 객체)의 방법으로 (A self받을 것을 기대하지 않는) 기존 기능을 적용하는 것입니다.

+1

좋은 답변 : 답변이 어떻게 나뉘어져서 왜 좋아하는지. 지금까지 @classmethod가 인스턴스를 필요로하지 않고 함수에 액세스 할 수있게되었습니다. 이게 내가 찾고 있었던 바로 그거야, 고마워. – marue

+0

@marue 환영합니다! – Marcin

+0

인스턴스에서 클래스 메서드를 호출하는 것은 잘못된 코딩 스타일이라고 말하고 싶습니다. 그렇게 할 이유가 없으며 혼란 만 일으킬 수 있습니다. 하지만 네가 작동합니다 (자바는 똑같은 것을 허용하지만, 인스턴스를 통해 정적 메소드를 호출 할 때 컴파일 경고를 발행합니다). – Voo

0

데코레이터 @classmethod를 추가하면 Java 또는 C++의 정적 메서드로 해당 메서드를 만들 예정입니다.(정적 메서드는 일반 용어입니다. )) 파이썬에는 @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는 클래스를 팩토리 으로 만들거나 클래스를 한 번만 초기화해야 할 때 유용합니다. 파일을 한 번 열어보고 피드 메서드를 사용하여 한 줄씩 파일을 읽습니다.

+1

(a) 정적 메소드는 다른 것입니다. (b) 클래스 방법은 모든 클래스에 의해 공유되지 않는다. – Marcin

+0

@Marcin이 내게 불분명 한 정의와 모든 것을 알려 주신 것에 대해 감사드립니다. –