Вы также можете вызывать class_foo используя класс. Фактически, если вы определяете что-то как classmethod , это, вероятно, потому, что вы собираетесь вызывать это из класса, а не из экземпляра класса. A.foo(1) вызвал бы ошибку типа, но A.class_foo(1) работает просто отлично:
В staticmethod ни self (экземпляр объекта), ни cls (класс) неявно не передаются в качестве первого аргумента. Они ведут себя как обычные функции, за исключением того, что вы можете вызывать их из экземпляра или класса:
a.static_foo(1) # executing static_foo(1)
A.static_foo('hi') # executing static_foo(hi)
Staticmethod используются для группировки функций, которые имеют некоторую логическую связь с классом, в класс.
foo это просто функция, но при вызове a.foo вы получаете не просто функцию, вы получаете "частично применяемую" версию функции с экземпляром объекта, a привязанным в качестве первого аргумента функции. foo ожидает 2 аргумента, в то время как a.foo ожидает только 1 аргумент.
a привязан к foo. Именно это подразумевается под термином "привязанный" ниже:
print(a.foo) # <bound method A.foo of <__main__.A object at 0xb7d52f0c>>
С a.class_foo, a не привязан к class_foo, скорее, класс A привязан к class_foo.
print(a.class_foo) # <bound method type.class_foo of <class '__main__.A'>>
Здесь, со staticmethod, даже если это метод, a.static_foo просто возвращает хорошую ole-функцию без привязки аргументов. static_foo ожидает 1 аргумент, и a.static_foo также ожидает 1 аргумент.
print(a.static_foo) # <function static_foo at 0xb7d479cc>
И, конечно, то же самое происходит, когда вы вызываете static_foo с помощью класса A вместо этого.
print(A.static_foo) # <function static_foo at 0xb7d479cc>
Ответ 2
staticmethod - это метод, который ничего не знает о классе или экземпляре, для которого он был вызван. Он просто получает аргументы, которые были переданы, без неявного первого аргумента.
С другой стороны, classmethod - это метод, которому передается класс, в котором он был вызван, или класс экземпляра, в котором он был вызван, в качестве первого аргумента. Это полезно, когда вы хотите, чтобы метод был фабрикой для класса: поскольку он получает фактический класс, для которого он был вызван в качестве первого аргумента, вы всегда можете создать экземпляр нужного класса, даже если задействованы подклассы. Обратите внимание, например, на то, как dict.fromkeys() метод class возвращает экземпляр подкласса при вызове в подклассе:
По сути, @classmethod создает метод, первым аргументом которого является класс, из которого он вызывается (а не экземпляр класса), @staticmethod не имеет никаких неявных аргументов.
Ответ 4
Чтобы решить, использовать ли @staticmethod или @classmethod, вам нужно заглянуть внутрь вашего метода. Если ваш метод обращается к другим переменным / методам в вашем классе, тогда используйте @classmethod. С другой стороны, если ваш метод не затрагивает никаких других частей класса, тогда используйте @staticmethod .
classApple:
_counter = 0
@staticmethod defabout_apple(): print('Apple is good for you.')
# note you can still access other member of the class # but you have to use the class instance # which is not very nice, because you have repeat yourself # # For example: # @staticmethod # print('Number of apples have been juiced: %s' % Apple._counter) # # @classmethod # print('Number of apples have been juiced: %s' % cls._counter) # # @classmethod is especially useful when you move your function to another class, # you don't have to rename the referenced class
@classmethod defmake_apple_juice(cls, number_of_apples): print('Making juice:') for i inrange(number_of_apples): cls._juice_this(i)