Подтвердить что ты не робот

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

type(self).do_something_with_the_class

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

4b9b3361

Ответ 1

Ваша догадка правильная - вы понимаете, как работает classmethod.

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

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

Об использовании этих экземпляров в экземплярах. Существует как минимум два основных способа использования метода class в экземпляре:

  • self.some_function() будет вызывать версию some_function для фактического типа self, а не класса, в котором этот вызов появляется (и не будет нуждаться в внимании, если класс будет переименован); и
  • В случаях, когда 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, значит, вы собираетесь сделать этот метод статическим методом java или С++. (статический метод общий термин Я думаю ;)) 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 и печатают его.

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

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

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