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

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

вопрос задан 25.09.2008
Daryl Spitzer
49126 репутация

24 ответов


  • 2403 рейтинг

    Возможно, пример кода поможет: обратите внимание на разницу в сигнатурах вызовов 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(,1)
    

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

    A.class_foo(1)
    # executing class_foo(,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)
    # <__main__.A object at 0xb7d52f0c>>
    

    С a.class_foo, a не связан с class_foo, скорее класс A связан с class_foo.

    print(a.class_foo)
    # >
    

    Здесь со статическим методом, хотя это и метод, a.static_foo просто возвращает хорошая функция ole без привязки аргументов. static_foo ожидает 1 аргумент и a.static_foo также ожидает 1 аргумент.

    print(a.static_foo)
    # 
    

    И, конечно, то же самое происходит, когда вы звоните static_foo с классом A.

    print(A.static_foo)
    # 
    
    ответ дан unutbu, с репутацией 523862, 3.11.2009
  • 675 рейтинг

    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, с репутацией 87720, 25.09.2008
  • 113 рейтинг

    В основном @classmethod создает метод, первым аргументом которого является класс, из которого он вызывается (а не экземпляр класса), @staticmethod не имеет никаких неявных аргументов.

    ответ дан Terence Simpson, с репутацией 2620, 25.09.2008
  • 76 рейтинг

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

    @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., с репутацией 1964, 3.11.2009
  • 57 рейтинг

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

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

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

    ответ дан Tom Neyland, с репутацией 5364, 3.11.2009
  • 46 рейтинг

    Чтобы решить, использовать ли @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., с репутацией 2394, 22.04.2016
  • 39 рейтинг

    В чем разница между @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)
    
    

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

    ответ дан Aaron Hall, с репутацией 153756, 23.01.2015
  • 27 рейтинг

    @decorators были добавлены в Python 2. 4 Если вы используете python & lt; 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, с репутацией 4582, 24.02.2012
  • 26 рейтинг

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

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

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

    ответ дан Nathan Tregillus, с репутацией 3436, 19.05.2015
  • 24 рейтинг

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

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

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

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

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

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

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

       @classmethod
       def some_class_method(cls, *args, **kwds):
           pass
      
    ответ дан Laxmi, с репутацией 2621, 3.10.2016
  • 19 рейтинг

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

    >>> class C(object):
    ...  pass
    ... 
    >>> def f():
    ...  pass
    ... 
    >>> staticmethod(f).__get__(None, C)
    
    >>> classmethod(f).__get__(None, C)
    >
    

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

    >>> class CMeta(type):
    ...  def foo(cls):
    ...   print cls
    ... 
    >>> class C(object):
    ...  __metaclass__ = CMeta
    ... 
    >>> C.foo()
    
    
    ответ дан Armin Ronacher, с репутацией 25958, 25.09.2008
  • 18 рейтинг

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

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

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

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

    • Фабричные методы , которые используются для создания экземпляра для класса, используя, например, некоторую предварительную обработку.
    • Статические методы, вызывающие статические методы : если вы разбили статические методы на несколько статических методов, вам не нужно жестко кодировать имя класса, а использовать методы класса
    ответ дан zangw, с репутацией 21935, 16.11.2015
  • 16 рейтинг

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

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

    ответ дан Tushar.PUCSD, с репутацией 869, 13.12.2015
  • 10 рейтинг

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

    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, с репутацией 7080, 29.09.2016
  • 8 рейтинг

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

    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, с репутацией 2227, 20.09.2016
  • 8 рейтинг

    Я начал изучать язык программирования на 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, с репутацией 2428, 10.10.2017
  • 5 рейтинг

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

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

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

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

    >>> 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, с репутацией 899, 14.01.2018
  • 4 рейтинг

    метод класса против статического метода в Python

    Метод класса

    Декоратор @classmethod - это встроенный декоратор функций, который является выражением, которое вычисляется после определения вашей функции. Результат этой оценки затеняет определение вашей функции.

    Метод класса получает класс как неявный первый аргумент, точно так же, как метод экземпляра получает экземпляр

    Синтаксис:

    class C(object):
        @classmethod
        def fun(cls, arg1, arg2, ...):
           ....
    
    fun: function that needs to be converted into a class method
    returns: a class method for function.
    
    • Метод класса - это метод, который связан с классом, а не объект класса.
    • У них есть доступ к состоянию класса, так как он принимает класс параметр, указывающий на класс, а не на экземпляр объекта.
    • Может изменять состояние класса, которое будет применяться ко всем экземплярам. класса. Например, он может изменить переменную класса, которая будет быть применимы ко всем случаям.

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

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

    Синтаксис:

    class C(object):
        @staticmethod
        def fun(arg1, arg2, ...):
            ...
    returns: a static method for function fun.
    
    • Статический метод - это также метод, который привязан к классу, а не объект класса.
    • Статический метод не может получить доступ или изменить состояние класса.
    • Он присутствует в классе, потому что метод имеет смысл присутствует в классе.

    Метод класса против статического метода

    • Метод класса принимает cls в качестве первого параметра, в то время как статический метод не нуждается в конкретных параметрах.
    • Метод класса может обращаться или изменять состояние класса, в то время как статический метод не могу получить доступ или изменить его.
    • Мы используем декоратор @classmethod в python для создания метода класса и мы используем декоратор @staticmethod для создания статического метода в python.

    Когда использовать что?

    • Обычно мы используем метод класса для создания фабричных методов. завод методы возвращают объект класса (аналог конструктора) для разные варианты использования.
    • Обычно мы используем статические методы для создания служебных функций.

    Как определить метод класса и статический метод?

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

    Давайте посмотрим на пример, чтобы понять разницу между ними обоими. Допустим, мы хотим создать класс Person. Теперь Python не поддерживает перегрузку методов, таких как C ++ или Java, поэтому мы используем методы класса для создания фабричных методов. В приведенном ниже примере мы используем метод класса для создания объекта person с года рождения.

    Как объяснено выше, мы используем статические методы для создания служебных функций. В приведенном ниже примере мы используем статический метод, чтобы проверить, взрослый человек или нет.

    Реализация

    # Python program to demonstrate 
    # use of class method and static method.
    from datetime import date
    
    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
        # a class method to create a Person object by birth year.
        @classmethod
        def fromBirthYear(cls, name, year):
            return cls(name, date.today().year - year)
    
        # a static method to check if a Person is adult or not.
        @staticmethod
        def isAdult(age):
            return age > 18
    
    person1 = Person('mayank', 21)
    person2 = Person.fromBirthYear('mayank', 1996)
    
    print person1.age
    print person2.age
    
    # print the result
    print Person.isAdult(22)
    

    Выход

    21
    21
    True
    

    Ссылка

    ответ дан Chirag Maliwal, с репутацией 1570, 22.01.2018
  • 3 рейтинг

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

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

    ответ дан vijay, с репутацией 46, 20.09.2017
  • 1 рейтинг

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

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

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

    ответ дан JawSaw, с репутацией 3060, 12.12.2017
  • 1 рейтинг

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

    class A(object):
        m=54
    
        @classmethod
        def class_method(cls):
            print "m is %d" % cls.m
    

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

    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, с репутацией 340, 1.12.2017
  • 1 рейтинг

    Мой вклад демонстрирует разницу между @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, с репутацией 511, 25.06.2018
  • -4 рейтинг
    #!/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, с репутацией 503, 18.11.2013
  • -5 рейтинг

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

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

    ответ дан Cathal Garvey, с репутацией 33, 17.12.2012