В чем разница между @staticmethod и @classmethod?

В чем разница между функцией, украшенной @staticmethod и один украшен @classmethod

2902 голоса | спросил Daryl Spitzer 26 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 26 Sep 2008 01:01:57 +0400 2008, 01:01:57

21 ответ


0

Может быть, немного примера кода поможет: обратите внимание на разницу в сигнатурах вызовов foo, class_foo и static_foo:

class A(object):
    def foo(self,x):
        print "executing foo(%s,%s)"%(self,x)

    @classmethod
    def class_foo(cls,x):
        print "executing class_foo(%s,%s)"%(cls,x)

    @staticmethod
    def static_foo(x):
        print "executing static_foo(%s)"%x    

a=A()

Ниже приведен обычный способ, которым экземпляр объекта вызывает метод. Экземпляр объекта, a, неявно передается в качестве первого аргумента.

a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)

При использовании методов класса класс экземпляра объекта неявно передается в качестве первого аргумента вместо self .

a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Вы также можете вызвать class_foo, используя класс. На самом деле, если вы определите что-то, чтобы быть метод класса, это, вероятно, потому, что вы собираетесь вызывать его из класса, а не из экземпляра класса. A.foo(1) вызвало бы ошибку TypeError, но A.class_foo(1) работает просто отлично:

A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)

Один из способов использования методов класса - создание наследуемых альтернативных конструкторов .


При использовании статических методов ни self (экземпляр объекта), ни cls (класс) неявно передается в качестве первого аргумента. Они ведут себя как простые функции, за исключением того, что вы можете вызывать их из экземпляра или класса:

a.static_foo(1)
# executing static_foo(1)

A.static_foo('hi')
# executing static_foo(hi)

Статические методы используются для группировки функций, которые имеют некоторую логическую связь с классом для класса.


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'>>

Здесь со статическим методом, даже если это метод, 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>
ответил unutbu 3 22009vEurope/Moscow11bEurope/MoscowTue, 03 Nov 2009 22:13:48 +0300 2009, 22:13:48
0

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

classmethod , с другой стороны, - это метод, передающий класс, к которому он был вызван, или класс экземпляра, к которому он был вызван, в качестве первого аргумента. Это полезно, когда вы хотите, чтобы метод был фабрикой для класса: поскольку он получает фактический класс, для которого он был вызван, в качестве первого аргумента, вы всегда можете создать экземпляр нужного класса, даже если задействованы подклассы. Посмотрите, например, как dict.fromkeys(), метод класса, возвращает экземпляр подкласса при вызове в подклассе:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 
ответил Thomas Wouters 26 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 26 Sep 2008 01:05:53 +0400 2008, 01:05:53
0

Официальные документы по питону:

@classmethod

  

Метод класса получает класс как   неявный первый аргумент, так же, как   Метод экземпляра получает экземпляр.   Чтобы объявить метод класса, используйте этот   идиома:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 
     

Форма @classmethod является функцией    декоратор - см. описание   определения функций в функции   определения для подробностей.

     

Это может быть вызвано либо в классе   (например, C.f()) или в экземпляре   (например, C().f()). Экземпляр   игнорируется за исключением его класса. Если   метод класса вызывается для производного   класс, объект производного класса   передан как подразумеваемый первый аргумент.

     

Методы класса отличаются от C ++   или статические методы Java. Если ты хочешь   см. staticmethod() в этом   раздел.

@staticmethod

  

Статический метод не получает   неявный первый аргумент. Чтобы объявить   статический метод, используйте эту идиому:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 
     

Форма @staticmethod является функцией    декоратор - см. описание   определения функций в функции   определения для подробностей.

     

Это может быть вызвано либо в классе   (например, C.f()) или в экземпляре   (например, C().f()). Экземпляр   игнорируется за исключением его класса.

     

Статические методы в Python похожи   к найденным в Java или C ++. Для   более продвинутая концепция, см.    classmethod() в этом разделе.

ответил Chris B. 3 22009vEurope/Moscow11bEurope/MoscowTue, 03 Nov 2009 22:23:19 +0300 2009, 22:23:19
0

Здесь небольшая статья вопрос

  

Функция @staticmethod - это не что иное, как функция, определенная внутри класса. Он вызывается без создания экземпляра класса первым. Это определение является неизменным с помощью наследования.

     Функция

@classmethod также может вызываться без создания экземпляра класса, но ее определение следует за Sub-классом, а не родительским классом, через наследование. Это потому, что первым аргументом функции @classmethod всегда должен быть cls (class).

ответил Tom Neyland 3 22009vEurope/Moscow11bEurope/MoscowTue, 03 Nov 2009 22:02:23 +0300 2009, 22:02:23
0

Чтобы решить, использовать ли @staticmethod или @classmethod . Если ваш метод обращается к другим переменным /методам в вашем классе, используйте @classmethod . С другой стороны, если ваш метод не касается каких-либо других частей класса, используйте @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_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 other class,
        #       you don't have to rename the class reference 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Make juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing %d...' % apple)
        cls._counter += 1
ответил Du D. 22 PMpFri, 22 Apr 2016 18:40:20 +030040Friday 2016, 18:40:20
0
  

В чем разница между @staticmethod и @classmethod в Python?

Возможно, вы видели код Python, подобный этому псевдокоду, который демонстрирует подписи различных типов методов и предоставляет строку документации для объяснения каждого из них:

class Foo(object):

    def a_normal_instance_method(self, arg_1, kwarg_2=None):
        '''
        Return a value that is a function of the instance with its
        attributes, and other arguments such as arg_1 and kwarg2
        '''

    @staticmethod
    def a_static_method(arg_0):
        '''
        Return a value that is a function of arg_0. It does not know the 
        instance or class it is called from.
        '''

    @classmethod
    def a_class_method(cls, arg1):
        '''
        Return a value that is a function of the class and other arguments.
        respects subclassing, it is called with the class it is called from.
        '''

Нормальный метод экземпляра

Сначала я объясню a_normal_instance_method. Это точно называется « метод экземпляра ». Когда используется метод экземпляра, он используется как частичная функция (в отличие от функции total, определенной для всех значений при просмотре в исходном коде), то есть при использовании первый из аргументов предопределен как экземпляр объект со всеми заданными атрибутами. Он имеет экземпляр объекта, связанный с ним, и он должен вызываться из экземпляра объекта. Как правило, он будет обращаться к различным атрибутам экземпляра.

Например, это экземпляр строки:

', '

если мы используем метод экземпляра, join в этой строке, чтобы присоединиться к другой итерации, вполне очевидно, что это функция экземпляра, в дополнение к функции итеративного списка, ['a', 'b', 'c']:

>>> ', '.join(['a', 'b', 'c'])
'a, b, c'

Связанные методы

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

Например, это связывает метод str.join с ':' экземпляр:

>>> join_with_colons = ':'.join 

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

>>> join_with_colons('abcde')
'a:b:c:d:e'
>>> join_with_colons(['FF', 'FF', 'FF', 'FF', 'FF', 'FF'])
'FF:FF:FF:FF:FF:FF'

Статический метод

Статический метод не принимает экземпляр в качестве аргумента.

Это очень похоже на функцию уровня модуля.

Однако функция уровня модуля должна находиться в модуле и специально импортироваться в другие места, где она используется.

Однако, если он присоединен к объекту, он будет удобно следовать за объектом через импорт и наследование.

Пример статического метода - str.maketrans, перемещенный из string модуль в Python 3. Он делает таблицу перевода пригодной для использования str.translate. Это выглядит довольно глупо при использовании из экземпляра строки, как показано ниже, но импорт функции из модуля string довольно неуклюжий и приятно иметь возможность вызывать его из класса, как в str.maketrans

# demonstrate same function whether called from instance or not:
>>> ', '.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}
>>> str.maketrans('ABC', 'abc')
{65: 97, 66: 98, 67: 99}

В Python 2 вы должны импортировать эту функцию из все менее полезного строкового модуля:

>>> import string
>>> 'ABCDEFG'.translate(string.maketrans('ABC', 'abc'))
'abcDEFG'

Метод класса

Метод класса похож на метод экземпляра в том, что он принимает неявный первый аргумент, но вместо того, чтобы брать экземпляр, он принимает класс. Часто они используются в качестве альтернативных конструкторов для лучшего семантического использования и поддерживают наследование.

Наиболее каноническим примером встроенного метода класса является dict.fromkeys. Он используется в качестве альтернативного конструктора dict (хорошо подходит для случаев, когда вы знаете, какие у вас ключи, и хотите получить для них значение по умолчанию.)

>>> dict.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

Когда мы создаем подкласс dict, мы можем использовать тот же конструктор, который создает экземпляр подкласса.

>>> class MyDict(dict): 'A dict subclass, use to demo classmethods'
>>> md = MyDict.fromkeys(['a', 'b', 'c'])
>>> md
{'a': None, 'c': None, 'b': None}
>>> type(md)
<class '__main__.MyDict'>

См. исходный код pandas для других похожих примеры альтернативных конструкторов, а также см. официальную документацию по Python по адресу classmethod и staticmethod

ответил Aaron Hall 23 Jpm1000000pmFri, 23 Jan 2015 23:01:20 +030015 2015, 23:01:20
0

@decorators были добавлены в python 2.4. Если вы используете python <2.4 вы можете использовать функции classmethod () и staticmethod ().

Например, если вы хотите создать фабричный метод (функция, возвращающая экземпляр другой реализации класса в зависимости от того, какой аргумент он получает), вы можете сделать что-то вроде:

class Cluster(object):

    def _is_cluster_for(cls, name):
        """
        see if this class is the cluster with this name
        this is a classmethod
        """ 
        return cls.__name__ == name
    _is_cluster_for = classmethod(_is_cluster_for)

    #static method
    def getCluster(name):
        """
        static factory method, should be in Cluster class
        returns a cluster object for the given name
        """
        for cls in Cluster.__subclasses__():
            if cls._is_cluster_for(name):
                return cls()
    getCluster = staticmethod(getCluster)

Также обратите внимание, что это хороший пример использования метода класса и статического метода, Статический метод явно принадлежит классу, поскольку он использует класс Cluster для внутреннего использования. Метод класса нуждается только в информации о классе, а не в экземпляре объекта.

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

ответил Jens Timmerman 24 FebruaryEurope/MoscowbFri, 24 Feb 2012 13:32:32 +0400000000pmFri, 24 Feb 2012 13:32:32 +040012 2012, 13:32:32
0

Думаю, лучше задать вопрос: «Когда бы вы использовали @classmethod vs @staticmethod?»

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

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

ответил Nathan Tregillus 19 Maypm15 2015, 18:27:13
0

Статические методы:

  • Простые функции без аргумента self.
  • Работа с атрибутами класса; не в атрибутах экземпляра.
  • Может вызываться как через класс, так и через экземпляр.
  • Встроенная функция staticmethod () используется для их создания.

Преимущества статических методов:

  • Локализует имя функции в классе
  • Он перемещает код функции ближе к месту его использования
  • Удобнее импортировать функции по сравнению с функциями уровня модуля, поскольку каждый метод не нужно специально импортировать.

    @staticmethod
    def some_static_method(*args, **kwds):
        pass
    

Методы класса:

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

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    
ответил Laxmi 3 +03002016-10-03T13:41:18+03:00312016bEurope/MoscowMon, 03 Oct 2016 13:41:18 +0300 2016, 13:41:18
0

@staticmethod просто отключает функцию по умолчанию как дескриптор метода. classmethod оборачивает вашу функцию в вызываемый контейнер, который передает ссылку на собственный класс в качестве первого аргумента:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)
<function f at 0x5c1cf0>
>>> classmethod(f).__get__(None, C)
<bound method type.f of <class '__main__.C'>>

На самом деле, classmethod накладные расходы времени выполнения, но позволяют получить доступ к классу-владельцу. В качестве альтернативы я рекомендую использовать метакласс и поместить методы класса в этот метакласс:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()
<class '__main__.C'>
ответил Armin Ronacher 26 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 26 Sep 2008 01:24:13 +0400 2008, 01:24:13
0

Полное руководство по использованию статических классов или абстрактные методы в Python - одна из хороших ссылок на эту тему, и кратко изложите ее следующим образом.

Функция

@staticmethod - это не что иное, как функция, определенная внутри класса. Он вызывается без создания экземпляра класса первым. Это определение является неизменным с помощью наследования.

  • Python не обязан создавать экземпляр метода для объекта.
  • Это облегчает читабельность кода и не зависит от состояния самого объекта;
Функция

@classmethod также может вызываться без создания экземпляра класса, но ее определение следует подклассу, а не классу Parent. через наследование может быть переопределено подклассом. Это потому, что первый аргумент для функции @classmethod всегда должен быть cls (class).

  • Фабричные методы , которые используются для создания экземпляра класса, используя, например, некоторую предварительную обработку.
  • Статические методы, вызывающие статические методы : если вы разбили статические методы на несколько статических методов, вам не следует жестко кодировать имя класса, а использовать методы класса
ответил zangw 16 12015vEurope/Moscow11bEurope/MoscowMon, 16 Nov 2015 05:00:50 +0300 2015, 05:00:50
0

Я начал изучать язык программирования на C ++, а затем на Java, а затем на Python, поэтому этот вопрос меня тоже очень беспокоил, пока я не понял простое использование каждого из них.

Метод класса: Python, в отличие от Java и C ++, не перегружен конструктором. И поэтому для достижения этого вы можете использовать classmethod. Следующий пример объяснит это

Давайте рассмотрим, что у нас есть класс Person, который принимает два аргумента first_name и last_name и создает экземпляр Person.

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

Теперь, если требование возникает там, где вам нужно создать класс, используя только одно имя, просто first_name, вы не могу сделать что-то подобное в python.

Это приведет к ошибке при попытке создать объект (экземпляр).

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    def __init__(self, first_name):
        self.first_name = first_name

Однако вы можете достичь того же, используя @classmethod, как указано ниже

class Person(object):

    def __init__(self, first_name, last_name):
        self.first_name = first_name
        self.last_name = last_name

    @classmethod
    def get_person(cls, first_name):
        return cls(first_name, "")

Статический метод : это довольно просто, он не привязан к экземпляру или классу, и вы можете просто вызвать его, используя имя класса.

Итак, скажем, в приведенном выше примере вам нужна проверка, что first_name не должен превышать 20 символов, вы можете просто сделать это.

@staticmethod  
def validate_name(name):
    return len(name) <= 20

и вы можете просто позвонить, используя Имя класса

Person.validate_name("Gaurang Shah")
ответил Gaurang Shah 10 +03002017-10-10T13:10:50+03:00312017bEurope/MoscowTue, 10 Oct 2017 13:10:50 +0300 2017, 13:10:50
0

Еще одно соображение, касающееся статического метода и классового метода, связано с наследованием. Скажем, у вас есть следующий класс:

class Foo(object):
    @staticmethod
    def bar():
        return "In Foo"

И затем вы хотите переопределить bar() в дочернем классе:

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"

Это работает, но обратите внимание, что теперь реализация bar() в дочернем классе (Foo2) больше не может использовать что-то специфическое для этого класса. Например, скажем, у Foo2 был метод с именем magic(), который вы хотите использовать в Foo2 реализации bar():

class Foo2(Foo):
    @staticmethod
    def bar():
        return "In Foo2"
    @staticmethod
    def magic():
        return "Something useful you'd like to use in bar, but now can't" 

Обходной путь здесь будет заключаться в вызове Foo2.magic() в bar(), но затем вы повторяете себя (если имя Foo2 изменится, вы должны будете не забыть обновить этот метод bar()).

Для меня это небольшое нарушение принципа открытия /закрытия , поскольку решение, принятое в Foo, влияет на вашу способность реорганизовывать общий код в производном классе (т. е. он менее открыт для расширения). Если бы bar() было бы classmethod, мы бы быть в порядке:

class Foo(object):
    @classmethod
    def bar(cls):
        return "In Foo"

class Foo2(Foo):
    @classmethod
    def bar(cls):
        return "In Foo2 " + cls.magic()
    @classmethod
    def magic(cls):
        return "MAGIC"

print Foo2().bar()

Дает: In Foo2 MAGIC

ответил Adam Parkin 29 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 29 Sep 2016 20:02:51 +0300 2016, 20:02:51
0

Позвольте мне сначала рассказать о сходстве метода, украшенного @classmethod vs @staticmethod.

Сходство . Их обоих можно вызывать для самого класса , а не только для экземпляра класса. Итак, оба они в каком-то смысле являются методами класса .

Разница . Метод класса получит сам класс в качестве первого аргумента, а метод статики - нет.

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

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. Call classmethod without any arg
>>> Klaus.classmthd()  
(__main__.Klaus,)  # the class gets passed as the first argument

# 2. Call classmethod with 1 arg
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. Call staticmethod without any arg
>>> Klaus.staticmthd()  
()

# 4. Call staticmethod with 1 arg
>>> Klaus.staticmthd('chumma')
('chumma',)
ответил Selva 14 Jpm1000000pmSun, 14 Jan 2018 17:07:39 +030018 2018, 17:07:39
0

Я попытаюсь объяснить основные различия на примере.

class A(object):
    x = 0

    def say_hi(self):
        pass

    @staticmethod
    def say_hi_static():
        pass

    @classmethod
    def say_hi_class(cls):
        pass

    def run_self(self):
        self.x += 1
        print self.x # outputs 1
        self.say_hi()
        self.say_hi_static()
        self.say_hi_class()

    @staticmethod
    def run_static():
        print A.x  # outputs 0
        # A.say_hi() #  wrong
        A.say_hi_static()
        A.say_hi_class()

    @classmethod
    def run_class(cls):
        print cls.x # outputs 0
        # cls.say_hi() #  wrong
        cls.say_hi_static()
        cls.say_hi_class()

1 - мы можем напрямую вызывать методы static и classmethods без инициализации

# A.run_self() #  wrong
A.run_static()
A.run_class()

2 - Статический метод не может вызывать метод self, но может вызывать другой статический метод и метод класса

3 - Статический метод принадлежит классу и не будет использовать объект вообще.

4 - Метод класса связан не с объектом, а с классом.

ответил Rizwan Mumtaz 20 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 20 Sep 2016 12:03:29 +0300 2016, 12:03:29
0

@classmethod: может использоваться для создания общего глобального доступа ко всем экземплярам, ​​созданным в этом классе ..... например, при обновлении записи несколькими пользователями .... В частности, я обнаружил, что это полезно при создании синглетонов ..:)

@static method: не имеет ничего общего с классом или экземпляром, связанным с ... но для удобства чтения можно использовать статический метод

ответил vijay 20 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowWed, 20 Sep 2017 19:57:20 +0300 2017, 19:57:20
0

Мой вклад демонстрирует разницу между @classmethod, @staticmethod и методы экземпляра, включая то, как экземпляр может косвенно вызывать @staticmethod. Но вместо того, чтобы косвенно вызывать @staticmethod из экземпляра, сделать его частным может быть более «питонным». Получение чего-то из закрытого метода здесь не продемонстрировано, но в основном это та же концепция.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # instance methods need a class instance and
    # can access the instance through 'self'
    def instance_method_1(self):
        return 'called from inside the instance_method_1()'

    def instance_method_2(self):
        # an instance outside the class indirectly calls the static_method
        return self.static_method() + ' via instance_method_2()'

    # class methods don't need a class instance, they can't access the
    # instance (self) but they have access to the class itself via 'cls'
    @classmethod
    def class_method(cls):
        return 'called from inside the class_method()'

    # static methods don't have access to 'cls' or 'self', they work like
    # regular functions but belong to the class' namespace
    @staticmethod
    def static_method():
        return 'called from inside the static_method()'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# works even if the class hasn't been instantiated
print(DemoClass.class_method() + '\n')
''' called from inside the class_method() '''

# works even if the class hasn't been instantiated
print(DemoClass.static_method() + '\n')
''' called from inside the static_method() '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> all methods types can be called on a class instance <<<<<
# instantiate the class
democlassObj = DemoClass()

# call instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' called from inside the instance_method_1() '''

# # indirectly call static_method through instance_method_2(), there's really no use
# for this since a @staticmethod can be called whether the class has been
# instantiated or not
print(democlassObj.instance_method_2() + '\n')
''' called from inside the static_method() via instance_method_2() '''

# call class_method()
print(democlassObj.class_method() + '\n')
'''  called from inside the class_method() '''

# call static_method()
print(democlassObj.static_method())
''' called from inside the static_method() '''

"""
# whether the class is instantiated or not, this doesn't work
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: unbound method instancemethod() must be called with
DemoClass instance as first argument (got nothing instead)
'''
"""
ответил Michael Swartz 25 J0000006Europe/Moscow 2018, 05:38:52
0

Методы класса, как следует из названия, используются для внесения изменений в классы, а не в объекты. Чтобы внести изменения в классы, они изменят атрибуты класса (не атрибуты объекта), поскольку именно так вы обновляете классы. По этой причине методы класса принимают класс (условно обозначаемый как «cls») в качестве первого аргумента.

class A(object):
    m=54

    @classmethod
    def class_method(cls):
        print "m is %d" % cls.m

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

class X(object):
    m=54 #will not be referenced

    @staticmethod
    def static_method():
        print "Referencing/calling a variable or function outside this class. E.g. Some global variable/function."
ответил Tushar Vazirani 1 FriEurope/Moscow2017-12-01T13:38:02+03:00Europe/Moscow12bEurope/MoscowFri, 01 Dec 2017 13:38:02 +0300 2017, 13:38:02
0

Анализируйте @staticmethod буквально , предоставляя различные идеи.

Обычный метод класса - это неявный динамический метод, который принимает экземпляр в качестве первого аргумента.
Напротив, статический метод не принимает экземпляр в качестве первого аргумента, поэтому он называется «статическим» .

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

ответил JawSaw 12 TueEurope/Moscow2017-12-12T12:40:50+03:00Europe/Moscow12bEurope/MoscowTue, 12 Dec 2017 12:40:50 +0300 2017, 12:40:50
0
#!/usr/bin/python
#coding:utf-8

class Demo(object):
    def __init__(self,x):
        self.x = x

    @classmethod
    def addone(self, x):
        return x+1

    @staticmethod
    def addtwo(x):
        return x+2

    def addthree(self, x):
        return x+3

def main():
    print Demo.addone(2)
    print Demo.addtwo(2)

    #print Demo.addthree(2) #Error
    demo = Demo(2)
    print demo.addthree(2)


if __name__ == '__main__':
    main()
ответил Zuckonit 18 12013vEurope/Moscow11bEurope/MoscowMon, 18 Nov 2013 09:53:17 +0400 2013, 09:53:17
0

Быстрый взлом других идентичных методов в iPython показывает, что @staticmethod дает незначительный прирост производительности (в наносекундах), но в противном случае это кажется, не выполняет никакой функции. Кроме того, любое повышение производительности, вероятно, будет устранено дополнительной работой по обработке метода с помощью staticmethod() во время компиляции (что происходит до любого кода выполнение при запуске сценария).

Ради читабельности кода я бы избегал @staticmethod, если только ваш метод не будет использоваться для работы, когда подсчет наносекунд считается .

ответил Cathal Garvey 17 MonEurope/Moscow2012-12-17T22:51:40+04:00Europe/Moscow12bEurope/MoscowMon, 17 Dec 2012 22:51:40 +0400 2012, 22:51:40

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132