python 스태틱 메소드 - 초보자를위한 @classmethod 및 @staticmethod의 의미?





5 Answers

Rostyslav Dzinko의 답변은 매우 적절합니다. 추가 생성자를 만들 때 @classmethod@staticmethod 선택 @classmethod 또 다른 이유를 강조 할 수 있다고 생각했습니다.

위의 예제에서 Rostyslav는 @classmethod from_string 을 Factory로 사용하여 허용되지 않는 매개 변수에서 Date 객체를 만들었습니다. 아래 코드와 같이 @staticmethod 를 사용하여 동일한 작업을 수행 할 수 있습니다.

class Date:
  def __init__(self, month, day, year):
    self.month = month
    self.day   = day
    self.year  = year


  def display(self):
    return "{0}-{1}-{2}".format(self.month, self.day, self.year)


  @staticmethod
  def millenium(month, day):
    return Date(month, day, 2000)

new_year = Date(1, 1, 2013)               # Creates a new Date object
millenium_new_year = Date.millenium(1, 1) # also creates a Date object. 

# Proof:
new_year.display()           # "1-1-2013"
millenium_new_year.display() # "1-1-2000"

isinstance(new_year, Date) # True
isinstance(millenium_new_year, Date) # True

따라서 new_yearmillenium_new_yearDate 클래스의 인스턴스입니다.

그러나 자세히 살펴보면 팩토리 프로세스는 무엇이든 상관없이 Date 객체를 생성하기 위해 하드 코딩됩니다. 이것이 의미하는 것은 Date 클래스가 서브 클래 싱 된 경우에도 서브 클래스는 여전히 (서브 클래스의 속성없이) 일반 Date 객체를 생성한다는 것입니다. 아래 예를 참조하십시오.

class DateTime(Date):
  def display(self):
      return "{0}-{1}-{2} - 00:00:00PM".format(self.month, self.day, self.year)


datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # False

datetime1.display() # returns "10-10-1990 - 00:00:00PM"
datetime2.display() # returns "10-10-2000" because it's not a DateTime object but a Date object. Check the implementation of the millenium method on the Date class

datetime2DateTime 의 인스턴스가 아닙니다. WTF? 왜냐하면 @staticmethod 데코레이터가 사용 되었기 때문입니다.

대부분의 경우 이는 바람직하지 않습니다. 원하는 클래스가 호출 된 클래스를 인식하는 Factory 메소드 인 경우 @classmethod 가 필요한 것입니다.

Date.millenium 다시 작성하기 (위 코드의 유일한 부분)

@classmethod
def millenium(cls, month, day):
    return cls(month, day, 2000)

class 가 하드 코딩되지 않고 오히려 학습된다는 것을 보장합니다. cls 는 모든 하위 클래스가 될 수 있습니다. 결과 object 는 올바르게 cls 의 인스턴스가됩니다. 그걸 시험해 봅시다.

datetime1 = DateTime(10, 10, 1990)
datetime2 = DateTime.millenium(10, 10)

isinstance(datetime1, DateTime) # True
isinstance(datetime2, DateTime) # True


datetime1.display() # "10-10-1990 - 00:00:00PM"
datetime2.display() # "10-10-2000 - 00:00:00PM"

그 이유는 지금까지 알다시피 @classmethod@staticmethod 대신 사용 @staticmethod

파이썬 클래스 <@

누군가가 파이썬에서 @classmethod@staticmethod 의 의미를 설명 할 수 있습니까? 차이점과 의미를 알아야합니다.

내가 이해하는 한, @classmethod 는 클래스에게 하위 클래스 나 상속 받아야하는 메소드라는 것을 알려준다. 그러나 그 점은 무엇입니까? @classmethod@staticmethod 또는 @ 정의를 추가하지 않고 클래스 메소드를 정의하는 것이 가장 좋은 이유는 무엇입니까?

tl; dr : 언제 사용해야합니까 ? 왜 사용해야합니까? 어떻게 사용해야합니까?

저는 C ++로 상당히 발전했습니다. 그래서 더 진보 된 프로그래밍 개념을 사용해서는 안됩니다. 가능한 경우 C ++ 예제를 제공하십시오.




언제 각각 사용 하는가?

@staticmethod 함수는 클래스 내부에 정의 된 함수 @staticmethod 입니다. 먼저 클래스를 인스턴스화하지 않고 호출 할 수 있습니다. 상속을 통해 정의가 변경되지 않습니다.

  • 파이썬은 객체에 대한 바운드 메소드 를 인스턴스화 할 필요가 없습니다.
  • 이것은 코드의 가독성을 높여줍니다 : @staticmethod를 보면 , 메소드가 객체 자체의 상태에 의존하지 않는다는 것을 알 수 있습니다.

@classmethod 함수는 클래스를 인스턴스화하지 않고도 호출 할 수 있지만 상속을 통해 상위 클래스가 아닌 하위 클래스가 정의되며 하위 클래스가 재정의 할 수 있습니다. @classmethod 함수의 첫 번째 인수는 항상 cls (class) 이어야하기 때문입니다.

  • 팩토리 메소드 . 예를 들어 일종의 사전 처리를 사용하여 클래스에 대한 인스턴스를 만드는 데 사용됩니다.
  • 정적 메서드를 호출하는 정적 메서드 : 여러 정적 메서드에서 정적 메서드를 분할하는 경우에는 클래스 이름을 하드 코딩하지 말고 클래스 메서드를 사용해야합니다.

here 주제에 대한 좋은 링크입니다.




약간의 편집

@staticmethod 호출되고있는 객체를 참조하지 않고 클래스 내에 메소드를 작성하는 방법. 그래서 self 나 cls와 같은 함축적 인 인수를 전달할 필요가 없습니다. 이것은 클래스 외부에서 작성된 것과 똑같은 방법으로 작성되지만 파이썬에서는 아무 쓸모가 없습니다. 왜냐하면이 메소드가 클래스의 일부가되어야하기 때문에 클래스 내부에 메소드를 캡슐화해야하기 때문에 @staticmethod가 편리합니다 케이스.

@classmethod 팩토리 메소드를 작성하고이 사용자 정의 속성을 클래스에 첨부 할 때 중요합니다. 이 특성은 상속 된 클래스에서 재정의 할 수 있습니다.

이 두 가지 방법을 비교하면 다음과 같습니다.




나는이 사이트의 초보자이며 위의 모든 대답을 읽고 원하는 정보를 얻었습니다. 그러나 나는 upvote 할 권리가 없다. 그래서 에 대한 해답을 알고 싶습니다.

  • @staticmethod 는 메소드의 첫 번째 매개 변수로 self 또는 cls가 필요하지 않습니다.
  • @staticmethod@classmethod 래핑 된 함수는 인스턴스 또는 클래스 변수에 의해 호출 될 수 있습니다.
  • @staticmethod 데코 레이팅 된 함수는 서브 클래스 상속이 @staticmethod 데코레이터에 의해 래핑 된 기본 클래스 함수를 덮어 쓸 수 없다는 '불변의 속성'에 영향을 미칩니다.
  • @classmethod 는 함수의 첫 번째 매개 변수로 cls (클래스 이름, 원하는 경우 변수 이름을 변경할 수 있지만 권고되지는 않음)가 필요합니다.
  • @classmethod 항상 하위 클래스 방식으로 사용되며, 하위 클래스 상속은 기본 클래스 함수의 효과를 바꿀 수 있습니다. 즉, @classmethod 래핑 된 기본 클래스 함수는 다른 하위 클래스로 덮어 쓸 수 있습니다.



즉, @classmehtod는 일반적인 메소드를 팩토리 메소드로 바꾼다.

예를 들어 살펴 보겠습니다.

class PythonBook:
    def __init__(self, name, author):
        self.name = name
        self.author = author
    def __repr__(self):
        return f'Book: {self.name}, Author: {self.author}'

@ 클래스 메소드가 없다면, 인스턴스를 하나씩 생성해야합니다.

book1 = PythonBook('Learning Python', 'Mark Lutz')
In [20]: book1
Out[20]: Book: Learning Python, Author: Mark Lutz
book2 = PythonBook('Python Think', 'Allen B Dowey')
In [22]: book2
Out[22]: Book: Python Think, Author: Allen B Dowey

예를 들어 @classmethod와 같이

class PythonBook:
    def __init__(self, name, author):
        self.name = name
        self.author = author
    def __repr__(self):
        return f'Book: {self.name}, Author: {self.author}'
    @classmethod
    def book1(cls):
        return cls('Learning Python', 'Mark Lutz')
    @classmethod
    def book2(cls):
        return cls('Python Think', 'Allen B Dowey')

그것을 시험하십시오 :

In [31]: PythonBook.book1()
Out[31]: Book: Learning Python, Author: Mark Lutz
In [32]: PythonBook.book2()
Out[32]: Book: Python Think, Author: Allen B Dowey

만나다? 인스턴스가 클래스 정의 내에서 성공적으로 작성되고 함께 수집됩니다.

결론적으로, @classmethod 데코레이터는 기존 메소드를 팩토리 메소드로 변환합니다. classmethods를 사용하면 필요한만큼 많은 대체 생성자를 추가 할 수 있습니다.




Related