Разница между staticmethod и classmethod

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

статические методы иногда лучше использовать в качестве функций уровня модуля в python ради чистоты. С помощью функции модуля легче импортировать только нужную функцию и предотвратить ненужное "." синтаксис (я смотрю на тебя Objective-C). Методы класса имеют большее применение, поскольку их можно использовать в сочетании с полиморфизмом для создания функций "фабричного шаблона". это потому, что методы класса получают класс как неявный параметр.

FistOfFury 06.12.2017 06:44

tl; dr >> по сравнению с обычными методами, к статическим методам и методам класса также можно получить доступ с помощью класса, но, в отличие от методов класса, статические методы неизменяемы через наследование.

imsrgadich 11.07.2018 18:02

Связанный доклад Раймонда Хеттингера по теме: youtube.com/watch?v=HTLu2DFOdTg

moooeeeep 10.09.2018 12:35

более точно youtube.com/watch?v=HTLu2DFOdTg&feature=youtu.be&t=2689 вам нужен только classmethod для альтернативных конструкторов. В противном случае вы можете использовать staticmethod и получить доступ к любому атрибуту класса (через. / Dot) с помощью более информативного фактического "CLASSNAME" вместо cls, как в classmethod

Robert Nowak 11.10.2019 14:22
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3 863
4
848 523
31
Перейти к ответу Данный вопрос помечен как решенный

Ответы 31

статический метод - это метод, который ничего не знает о классе или экземпляре, для которого он был вызван. Он просто получает переданные аргументы, без неявного первого аргумента. В 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
>>> 

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

Tony Meyer 26.09.2008 14:10

Отсюда только «принципиально» бесполезно. Такая организация, а также внедрение зависимостей являются допустимым использованием статических методов, но поскольку модули, а не классы, как в Java, являются основными элементами организации кода в Python, их использование и полезность редки.

Thomas Wouters 26.09.2008 17:40

Что логично в определении метода внутри класса, если он не имеет ничего общего ни с классом, ни с его экземплярами?

Ben James 12.03.2010 12:11

Может, ради наследства? Статические методы можно наследовать и переопределять так же, как методы экземпляра и методы класса, и поиск работает должным образом (в отличие от Java). Статические методы на самом деле не разрешаются статически независимо от того, вызываются ли они в классе или экземпляре, поэтому единственное различие между классовыми и статическими методами - это неявный первый аргумент.

haridsv 08.04.2010 05:32

Они также создают более чистое пространство имен и упрощают понимание того, что функция как-то связана с классом.

Imbrondir 22.08.2011 15:58

@BenJames: статический метод должен иметь какое-то отношение к классу, в котором он определен, ему просто не нужны ни данные класса, ни данные экземпляра для выполнения своей работы. (см. stackoverflow.com/questions/7855237)

Ethan Furman 08.11.2011 23:50

Итак, что лучше: наличие Math класс с такими методами, как sin, cos и т.д., или наличие Math модуль с функциями sin, cos и т.д. Мне кажется, что последнее было бы предпочтительнее, поэтому мне трудно думать о Возможный случай, когда будет полезен статический метод. Я полагаю, что вспомогательные методы - это потенциальный случай, но если помощник настолько универсален, что ему не нужно ничего из класса или экземпляра класса, вам действительно нужно задаться вопросом, не будет ли он лучше служить служебной программой в библиотеке.

Adam Parkin 03.03.2012 03:17

Когда у вас есть экземпляр класса, его часто проще вызвать inst.method(), чем module.method(). Иногда вы даже не знаете, какой модуль вы используете, в конце концов, Python является динамический язык ...

Jonathan 13.04.2012 20:04

-1: Этот ответ A) дает очень важную особенность метода класса в качестве объяснения его полезности (поэтому они полезны только при создании подкласса, чтобы позволить вам имя подкласса, В самом деле?), А B) подразумевает «статический методы должны быть модульными методами », что, хотя семантически и является, имеет смысл много или имеет смысл использовать их если ваш модуль определяет много классов, и данная вспомогательная функция применяется только к данному классу. Так что очень плохой ответ с большим количеством заблуждений imho.

MestreLion 03.05.2012 13:40

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

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

Один из возможных недостатков метакласса, который сразу же приходит мне в голову, заключается в том, что вы не можете вызвать метод класса непосредственно в экземпляре. c = C(); c.foo() вызывает AttributeError, вам нужно будет сделать type(c).foo(). Это также можно считать функцией - хотя я не могу придумать, зачем вам это нужно.

Aaron Hall 15.06.2016 00:57

Здесь - короткая статья по этому вопросу

@staticmethod function is nothing more than a function defined inside a class. It is callable without instantiating the class first. It’s definition is immutable via inheritance.

@classmethod function also callable without instantiating the class, but its definition follows Sub class, not Parent class, via inheritance. That’s because the first argument for @classmethod function must always be cls (class).

Значит ли это, что с помощью статического метода я всегда привязан к родительскому классу, а с помощью метода класса я привязан к классу, в котором я объявляю метод класса (в данном случае подкласс)?

Mohan Gulati 03.11.2009 22:06

Нет. Используя статический метод, вы совсем не связаны; неявный первый параметр отсутствует. Используя classmethod, вы получаете в качестве неявного первого параметра класс, для которого вы вызвали метод (если вы вызвали его непосредственно для класса), или класс экземпляра, для которого вы вызвали метод (если вы вызвали его для экземпляра).

Matt Anderson 03.11.2009 22:18

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

MestreLion 03.05.2012 14:01

«Это определение неизменяемо через наследование». не имеет смысла в Python, вы можете просто переопределить статический метод.

c z 17.09.2019 18:20
Ответ принят как подходящий

Может быть, вам поможет небольшой пример кода: обратите внимание на разницу в сигнатуре вызовов 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_fooa не привязан к class_foo, скорее, класс A привязан к class_foo.

print(a.class_foo)
# <bound method type.class_foo of <class '__main__.A'>>

Здесь со статическим методом, даже если это метод, a.static_foo просто возвращает хорошая старая функция без привязки аргументов. 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>

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

Alcott 19.09.2011 07:08

@Alcott: вы можете переместить функцию в класс, потому что она логически принадлежит классу. В исходном коде Python (например, multiprocessing, turtle, dist-packages) он используется для «скрытия» «закрытых» функций с одним подчеркиванием из пространства имен модуля. Однако его использование в значительной степени сконцентрировано всего в нескольких модулях - возможно, это указывает на то, что это в основном стилистическая вещь. Хотя я не смог найти ни одного примера этого, @staticmethod может помочь организовать ваш код, будучи переопределенным подклассами. Без него у вас были бы варианты функции, плавающие в пространстве имен модуля.

unutbu 19.09.2011 14:34

... вместе с некоторыми пояснениями по где и Почему для использования экземпляров, классов или статических методов. Вы не сказали ни слова об этом, но ОП не спрашивал об этом.

MestreLion 03.05.2012 13:50

@Alcott: как сказал unutbu, статические методы - это организационная / стилистическая особенность. Иногда у модуля много классов, и некоторые вспомогательные функции логически привязаны к определенному классу, а не к другим, поэтому имеет смысл не «засорять» модуль множеством «бесплатных функций», и лучше использовать статические метод, чем полагаться на плохой стиль смешивания классов и определений функций вместе в коде, чтобы показать, что они «связаны»

MestreLion 03.05.2012 13:55

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

@classmethod

A class method receives the class as implicit first argument, just like an instance method receives the instance. To declare a class method, use this idiom:

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

The @classmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class. If a class method is called for a derived class, the derived class object is passed as the implied first argument.

Class methods are different than C++ or Java static methods. If you want those, see staticmethod() in this section.

@staticmethod

A static method does not receive an implicit first argument. To declare a static method, use this idiom:

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

The @staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.

It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.

Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod() in this section.

В документах нет ошибки? Не должно быть статического метода: «И экземпляр, и его класс игнорируются». вместо «Экземпляр игнорируется, кроме его класса»?

mirek 02.03.2020 18:33

Это может быть ошибка вырезания и вставки, но, строго говоря, вы не можете вызвать метод класса, если игнорируете класс.

Aaron Bentley 15.05.2020 04:54

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

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

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

«В противном случае, кажется, не выполняет никакой функции»: не совсем верно. См. Обсуждение выше.

Keith Pinson 17.12.2012 23:46

What is the difference between @staticmethod and @classmethod in 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. Это точно называется «метод экземпляра». Когда используется метод экземпляра, он используется как частичная функция (в отличие от общей функции, определенной для всех значений при просмотре в исходном коде), то есть при использовании первый из аргументов предопределен как экземпляр объект со всеми заданными ему атрибутами. К нему привязан экземпляр объекта, и он должен вызываться из экземпляра объекта. Как правило, он будет обращаться к различным атрибутам экземпляра.

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

', '

если мы используем метод экземпляра 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.

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

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

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

В этом вопросе упоминается доступ частных членов класса. Я хочу подчеркнуть, что (в зависимости от вашего определения частного) @staticmethod имеет другой уровень доступа, чем @classmethod. Первый не должен обращаться к частным членам класса класса

joel 14.08.2020 00:37

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

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

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

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

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

Спасибо @zangw - унаследованная неизменяемость статической функции, кажется, является ключевым отличием

hard_working_ant 02.05.2018 06:38

Чтобы решить, использовать ли @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

в чем будет преимущество classmethod и cls._counter перед staticmethod и Apple._counter

Robert Nowak 11.10.2019 13:38

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

kiamlaluno 13.11.2019 01:55

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

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 - мы можем напрямую вызывать статические методы и методы классов без инициализации

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

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

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

4- Метод класса привязан не к объекту, а к классу.

объявление 2: Вы уверены? Как статический метод мог вызвать метод класса? У него нет ссылки на него (на его класс).

mirek 02.03.2020 19:31

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

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

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

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

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

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

Также: историческая справка: Гвидо Ван Россум (создатель Python) однажды назвал staticmethod «несчастным случаем»: https://mail.python.org/pipermail/python-ideas/2012-May/014969.html

we all know how limited static methods are. (They're basically an accident -- back in the Python 2.2 days when I was inventing new-style classes and descriptors, I meant to implement class methods but at first I didn't understand them and accidentally implemented static methods first. Then it was too late to remove them and only provide class methods.

Также: https://mail.python.org/pipermail/python-ideas/2016-July/041189.html

Honestly, staticmethod was something of a mistake -- I was trying to do something like Java class methods but once it was released I found what was really needed was classmethod. But it was too late to get rid of staticmethod.

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

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

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

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

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

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

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

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    

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

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

Я начал изучать язык программирования с 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

и вы можете просто вызвать, используя class name

Person.validate_name("Gaurang Shah")

Это старый пост, но более питонический способ добиться, чтобы конструктор принимал один или два аргумента, использовал бы def __init__(self, first_name, last_name = "") вместо метода класса get_person. И в этом случае результат будет точно таким же.

akarilimano 18.09.2019 01:08

Методы класса, как следует из названия, используются для внесения изменений в классы, а не в объекты. Чтобы внести изменения в классы, они изменят атрибуты класса (не атрибуты объекта), поскольку именно так вы обновляете классы. Это причина того, что методы класса принимают класс (обычно обозначаемый как 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."

методы не всегда вносят изменения

joel 14.08.2020 00:19

Проанализируйте @staticmethod буквально, предоставив различную информацию.

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

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

Позвольте мне сначала рассказать о сходстве между методом, украшенным @classmethod, и @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',)

Мой вклад демонстрирует разницу между @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)
'''
"""

Возможно, вы захотите рассмотреть разницу между:

class A:
    def foo():  # no self parameter, no decorator
        pass

и

class B:
    @staticmethod
    def foo():  # no self parameter
        pass

Это изменилось между python2 и python3:

python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

Таким образом, использование @staticmethod для методов, вызываемых только непосредственно из класса, стало необязательным в python3. Если вы хотите вызывать их как из класса, так и из экземпляра, вам все равно нужно использовать декоратор @staticmethod.

Остальные случаи хорошо освещены в unutbus ответе.

Отличается только первый аргумент:

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

Подробнее...

нормальный метод

Когда вызывается метод объекта, ему автоматически предоставляется дополнительный аргумент self в качестве первого аргумента. То есть метод

def f(self, x, y)

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

метод класса

Когда метод украшен

@classmethod
def f(cls, x, y)

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

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

Когда метод украшен

@staticmethod
def f(x, y)

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

обычаи

  • classmethod в основном используется для альтернативных конструкторов.
  • staticmethod не использует состояние объекта. Это может быть функция, внешняя по отношению к классу. Он помещается внутри класса только для группировки функций с аналогичной функциональностью (например, как статические методы класса Math в Java).
class Point
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @classmethod
    def frompolar(cls, radius, angle):
        """The `cls` argument is the `Point` class itself"""
        return cls(radius * cos(angle), radius * sin(angle))

    @staticmethod
    def angle(x, y):
        """this could be outside the class, but we put it here 
just because we think it is logically related to the class."""
        return atan(y, x)


p1 = Point(3, 2)
p2 = Point.frompolar(3, pi/4)

angle = Point.angle(3, 2)

Я думаю, что предоставление чисто Python-версии staticmethod и classmethod поможет понять разницу между ними на уровне языка.

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

class StaticMethod(object):
    "Emulate PyStaticMethod_Type() in Objects/funcobject.c"

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

    def __get__(self, obj, objtype=None):
        return self.f


class ClassMethod(object):
    "Emulate PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

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

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

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

Надеюсь, я был чист!

staticmethod не имеет доступа к атрибутам объекта, класса или родительских классов в иерархии наследования. Его можно вызвать непосредственно в классе (без создания объекта).

classmethod не имеет доступа к атрибутам объекта. Однако он может получить доступ к атрибутам класса и родительских классов в иерархии наследования. Его можно вызвать непосредственно в классе (без создания объекта). Если вызывается у объекта, то это то же самое, что и обычный метод, который не обращается к self.<attribute(s)> и обращается только к self.__class__.<attribute(s)>.

Думаю, у нас есть класс с b=2, мы создадим объект и переустановим его на b=4. Статический метод не может получить доступ ни к чему из предыдущего. Classmethod может получить доступ только к .b==2 через cls.b. Обычный метод может получить доступ как к .b==4 через self.b, так и к .b==2 через self.__class__.b.

Мы могли бы следовать стилю KISS (будь простым, глупым): не использовать статические методы и методы классов, не использовать классы без их создания, обращаться только к атрибутам объекта self.attribute(s). Есть языки, в которых ООП реализовано таким образом, и я думаю, что это неплохая идея. :)

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

mirek 02.03.2020 19:14

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

joel 14.08.2020 00:18

При создании подклассов возникает одно довольно важное практическое различие. Если не возражаете, я возьму пример @unutbu:

class A: 
    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)

class B(A):
    pass

В class_foo метод знает, для какого класса он вызван:

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

В static_foo нет способа определить, вызывается ли он на A или B:

A.static_foo(1)
# => executing static_foo(1)
B.static_foo(1)
# => executing static_foo(1)

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

class A:
    @classmethod
    def class_qux(cls, x):
        print(f"executing class_qux({cls}, {x})")
    
    @classmethod
    def class_bar(cls, x):
        cls.class_qux(x)

    @staticmethod
    def static_bar(x):
        A.class_qux(x)

class B(A):
    pass

A.class_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.class_bar(1)
# => executing class_qux(<class '__main__.B'>, 1)
A.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)
B.static_bar(1)
# => executing class_qux(<class '__main__.A'>, 1)

Метод экземпляра:

+Может изменить состояние экземпляра объекта

+Может изменить состояние класса

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

-Не могу изменить состояние экземпляра объекта

+Может изменить состояние класса

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

-Не могу изменить состояние экземпляра объекта

-Не могу изменить состояние класса

class MyClass:
    ''' 
    Instance method has a mandatory first attribute self which represent the instance itself. 
    Instance method must be called by a instantiated instance.
    '''
    def method(self):
        return 'instance method called', self
    
    '''
    Class method has a mandatory first attribute cls which represent the class itself. 
    Class method can be called by an instance or by the class directly. 
    Its most common using scenario is to define a factory method.
    '''
    @classmethod
    def class_method(cls):
        return 'class method called', cls
    
    '''
    Static method doesn’t have any attributes of instances or the class. 
    It also can be called by an instance or by the class directly. 
    Its most common using scenario is to define some helper or utility functions which are closely relative to the class.
    '''
    @staticmethod
    def static_method():
        return 'static method called'


obj = MyClass()
print(obj.method())
print(obj.class_method()) # MyClass.class_method()
print(obj.static_method()) # MyClass.static_method()

выход:

('instance method called', <__main__.MyClass object at 0x100fb3940>)
('class method called', <class '__main__.MyClass'>)
static method called

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

Статические методы используются для выполнения некоторых служебных задач, а методы классов используются для заводских методов. Фабричные методы могут возвращать объекты класса для различных вариантов использования.

И напоследок небольшой пример для лучшего понимания:

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

    @classmethod
    def get_from_string(cls, name_string: str):
        first_name, last_name = name_string.split()
        if Student.validate_name(first_name) and Student.validate_name(last_name):
            return cls(first_name, last_name)
        else:
            print('Invalid Names')

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


stackoverflow_student = Student.get_from_string('Name Surname')
print(stackoverflow_student.first_name) # Name
print(stackoverflow_student.last_name) # Surname

Python поставляется с несколькими встроенными декораторами. Большая тройка:

@classmethod
@staticmethod
@property

Декоратор @classmethod может быть вызван с экземпляром класса или непосредственно самим классом в качестве его первого аргумента.

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

Рассмотрим следующий класс:

class DecoratorTest(object):

    def __init__(self):
        pass

    def doubler(self, x):
        print("running doubler")
        return x*2

    @classmethod
    def class_doubler(klass, x):
        print("running doubler: %s" % klass)
        return x*2

    @staticmethod
    def static_doubler(x):
        print("running quad")
        return x*2

decor = DecoratorTest()

Посмотрим, как это работает:

print(decor.doubler(5))
# running doubler
# 10

print(decor.class_doubler(5))
# running doubler: <class '__main__.DecoratorTest'> 
# 10
print(DecoratorTest.class_doubler(5))
# running doubler: <class '__main__.DecoratorTest'> 
# 10

print(DecoratorTest.static_doubler(5))
# running doubler 
# 10
print(decor.static_doubler(5))
# running doubler 
# 10

print(decor.doubler)
# <bound method DecoratorTest.doubler of <__main__.DecoratorTest object at 0x7f90e74fd150>> 
print(decor.class_doubler)
# <bound method DecoratorTest.class_doubler of <class '__main__.DecoratorTest'>> 
print(decor.static_doubler)
# <function DecoratorTest.static_doubler at 0x7f90e7447440> 

tldr;

staticmethod - это, по сути, функция, связанная с классом (и, следовательно, с его экземплярами).

classmethod по сути является наследуемым staticmethod.

Подробнее см. В отличных ответах других.

Сначала давайте начнем с примера кода, который мы будем использовать для понимания обеих концепций:

class Employee:

    NO_OF_EMPLOYEES = 0
  
    def __init__(self, first_name, last_name, salary):
        self.first_name = first_name
        self.last_name = last_name
        self.salary = salary
        self.increment_employees()

    def give_raise(self, amount):
        self.salary += amount

    @classmethod
    def employee_from_full_name(cls, full_name, salary):
        split_name = full_name.split(' ')
        first_name = split_name[0]
        last_name = split_name[1]
        return cls(first_name, last_name, salary)

    @classmethod
    def increment_employees(cls):
        cls.NO_OF_EMPLOYEES += 1

    @staticmethod
    def get_employee_legal_obligations_txt():
        legal_obligations = """
        1. An employee must complete 8 hours per working day
        2. ...
        """
        return legal_obligations

Метод класса

Метод класса принимает сам класс как неявный аргумент и - необязательно - любые другие аргументы, указанные в определении. Важно понимать, что метод класса не имеет доступа к экземплярам объекта (в отличие от методов экземпляра). Следовательно, методы класса не могут использоваться для изменения состояния экземпляра объекта, но вместо этого они могут изменять состояние класса, которое является общим для всех экземпляров этого класса. Методы класса обычно полезны, когда нам нужно получить доступ к самому классу - например, когда мы хотим создать фабричный метод, то есть метод, который создает экземпляры класса. Другими словами, методы класса могут служить альтернативными конструкторами.

В нашем примере кода экземпляр Employee может быть создан с помощью трех аргументов; first_name, last_name и salary.

employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.first_name)
print(employee_1.salary)

'Andrew'
85000

Теперь предположим, что есть вероятность, что имя сотрудника может быть указано в одном поле, в котором имя и фамилия разделены пробелом. В этом случае мы могли бы использовать наш метод класса employee_from_full_name, который принимает всего три аргумента. Первый - это сам класс, который является неявным аргументом, что означает, что он не будет предоставлен при вызове метода - Python автоматически сделает это за нас:

employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(employee_2.first_name)
print(employee_2.salary)

'John'
95000

Обратите внимание, что employee_from_full_name также можно вызывать из экземпляров объекта, хотя в данном контексте это не имеет большого смысла:

employee_1 = Employee('Andrew', 'Brown', 85000)
employee_2 = employee_1.employee_from_full_name('John Black', 95000)

Еще одна причина, по которой мы можем захотеть создать метод класса, - это когда нам нужно изменить состояние класса. В нашем примере переменная класса NO_OF_EMPLOYEES отслеживает количество сотрудников, работающих в настоящее время в компании. Этот метод вызывается каждый раз, когда создается новый экземпляр Employee, и он соответственно обновляет счетчик:

employee_1 = Employee('Andrew', 'Brown', 85000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')
employee_2 = Employee.employee_from_full_name('John Black', 95000)
print(f'Number of employees: {Employee.NO_OF_EMPLOYEES}')

Number of employees: 1
Number of employees: 2

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

С другой стороны, в статических методах ни экземпляр (например, self), ни сам класс (например, cls) не передаются в качестве неявного аргумента. Это означает, что такие методы не могут получить доступ к самому классу или его экземплярам. Теперь можно утверждать, что статические методы бесполезны в контексте классов, поскольку они также могут быть помещены во вспомогательные модули вместо того, чтобы добавлять их в качестве членов класса. В объектно-ориентированном программировании важно структурировать классы в логические блоки, и поэтому статические методы весьма полезны, когда нам нужно добавить метод в класс просто потому, что он логически принадлежит классу. В нашем примере статический метод get_employee_legal_obligations_txt просто возвращает строку, содержащую юридические обязательства каждого сотрудника компании. Эта функция не взаимодействует ни с самим классом, ни с каким-либо экземпляром. Его можно было бы поместить в другой вспомогательный модуль, однако он имеет отношение только к этому классу, и поэтому мы должны поместить его в класс Employee.

К статическому методу можно получить доступ напрямую из самого класса.

print(Employee.get_employee_legal_obligations_txt())


    1. An employee must complete 8 hours per working day
    2. ...

или из экземпляра класса:

employee_1 = Employee('Andrew', 'Brown', 85000)
print(employee_1.get_employee_legal_obligations_txt())


    1. An employee must complete 8 hours per working day
    2. ...

использованная литература

Другие вопросы по теме