Когда я должен использовать @classmethod и когда метод def (self)?


при интеграции приложения 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 сам (the class, а не экземпляр). Я не совсем понимаю, почему это существует, потому что я всегда мог это сделать:

type(self).do_something_with_the_class

это просто для ясности, или я пропустил самую важную часть: жуткие и увлекательные вещи, которые не могли быть сделаны без него?

2 59

2 ответа:

ваша догадка верна - вы понимаете какclassmethod s работа.

почему эти методы могут быть вызваны как на экземпляре, так и на классе (в обоих случаях объект класса будет передан в качестве первого аргумента):

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()

на использование этих экземпляров: есть по крайней мере два основных использования для вызова classmethod на экземпляре:

  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) быть методом для класса (или объекта).

Если вы добавляете decorator @classmethod, это означает, что вы собираетесь сделать этот метод как статический метод java или C++. ( статический метод это общий срок Я думаю ;) ) Python также имеет @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 и распечатать его.

и все классы использование того же имени в той же области или экземплярах, построенных с этим классом, будет совместно использовать эти методы. Есть только один Тестметод.cls_var а также есть только один Тестметод.class_method (), TestMethod.static_method ()

и важный вопрос. почему эти методы будут необходимы.

classmethod или staticmethod полезен, когда вы делаете этот класс как фабрику или когда вам нужно инициализировать свой класс только один раз. как открыть файл один раз, и с помощью метода подачи для чтения файл строка за строкой.