Когда я должен использовать @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 ответа:
ваша догадка верна - вы понимаете как
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 на экземпляре:
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
) быть методом для класса (или объекта).
Если вы добавляете 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 полезен, когда вы делаете этот класс как фабрику или когда вам нужно инициализировать свой класс только один раз. как открыть файл один раз, и с помощью метода подачи для чтения файл строка за строкой.