[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

Question

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

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

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

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




클래스 메소드는 클래스 상태를 수정할 수 있으며 클래스에 바인딩되며 cls를 매개 변수로 포함합니다.

정적 메서드는 클래스 상태를 수정할 수 없으며 클래스에 바인딩되어 클래스 또는 인스턴스를 알지 못합니다.

class empDetails:
    def __init__(self,name,sal):
        self.name=name
        self.sal=sal
    @classmethod
    def increment(cls,name,none):
        return cls('yarramsetti',6000 + 500)
    @staticmethod
    def salChecking(sal):
        return sal > 6000

emp1=empDetails('durga prasad',6000)
emp2=empDetails.increment('yarramsetti',100)
# output is 'durga prasad'
print emp1.name
# output put is 6000
print emp1.sal
# output is 6500,because it change the sal variable
print emp2.sal
# output is 'yarramsetti' it change the state of name variable
print emp2.name
# output is True, because ,it change the state of sal variable
print empDetails.salChecking(6500)



어떤 하위 클래스가 메서드를 호출하는지에 따라 메서드의 동작을 변경하려는 경우 @classmethod 사용합니다. 클래스 메소드에서 호출 클래스에 대한 참조가 있다는 것을 기억하십시오.

정적을 사용하는 동안 하위 클래스간에 동작이 변경되지 않도록하고 싶습니다.

예:

class Hero:

  @staticmethod
  def say_hello():
     print("Helllo...")

  @classmethod
  def say_class_hello(cls):
     if(cls.__name__=="HeroSon"):
        print("Hi Kido")
     elif(cls.__name__=="HeroDaughter"):
        print("Hi Princess")

class HeroSon(Hero):
  def say_son_hello(self):
     print("test  hello")



class HeroDaughter(Hero):
  def say_daughter_hello(self):
     print("test  hello daughter")


testson = HeroSon()

testson.say_class_hello() #Output: "Hi Kido"

testson.say_hello() #Outputs: "Helllo..."

testdaughter = HeroDaughter()

testdaughter.say_class_hello() #Outputs: "Hi Princess"

testdaughter.say_hello() #Outputs: "Helllo..."



staticmethod와 classmethod를 사용하는 것과 사용하지 않는 것의 차이점을 보여주는 간단한 예제를 작성하려고했습니다. 코드는 다음과 같습니다.

#without decorator:
class Duck(object):
    def sound(self):
        print("Quack")


#pay attention to the "sound" function:

#with @staticmethod
class Cat(object):
    @staticmethod
    def sound():
        print("Meow")

#with @classmethod
class Dog(object):
    @classmethod
    def sound(self):
        print("woof")


#notice the differences between calling them:
Duck().sound()
Cat.sound()
Dog.sound()

#prints:
"""
Quack
Meow
woof
"""



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

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



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

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

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

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

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



Related