В чем разница для следующих двух функций? [Дубликат]

== проверяет ссылки на объекты, .equals() проверяет строковые значения.

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

Для Например:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

Но будьте осторожны с нулями!

== обрабатывает строки null в порядке, но вызов .equals() из пустой строки приведет к исключению:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Итак, если вы знаете, что fooString1 может но не менее очевидно, что он проверяет значение null (из Java 7):

System.out.print(Objects.equals(fooString1, "bar"));
2684
задан Vadim Kotov 1 January 2018 в 14:28
поделиться

25 ответов

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

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


С помощью staticmethods ни один 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'>>

Здесь, с помощью метода static, хотя это метод, 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>
2330
ответ дан Community 16 August 2018 в 03:38
поделиться
  • 1
    Я не понимаю, что такое улов для использования staticmethod. мы можем просто использовать простую функцию вне класса. – Alcott 19 September 2011 в 04:08
  • 2
    @Alcott: вы можете переместить функцию в класс, потому что она логически принадлежит классу. В исходном коде Python (например, многопроцессорности, черепахе, dist-пакетах) он используется для «скрытия», однострочный символ "частный" функции из пространства имен модулей. Его использование, однако, сильно сконцентрировано всего в нескольких модулях - возможно, это указывает на то, что это в основном стилистическая вещь. Хотя я не мог найти ни одного примера этого, @staticmethod может помочь организовать ваш код, будучи переопределяемым подклассами. Без этого у вас будут варианты функции, плавающие в пространстве имен модулей. – unutbu 19 September 2011 в 11:34
  • 3
    ... наряду с некоторым объяснением в , где и почему используется либо экземпляр, либо класс, либо статические методы. Вы не дали ни слова об этом, но и ОП не спросил об этом. – MestreLion 3 May 2012 в 10:50
  • 4
    @Alcott: как сказал unutbu, статические методы - это организация / стилистическая функция. Иногда модуль имеет много классов, а некоторые вспомогательные функции логически привязаны к данному классу, а не к другим, поэтому имеет смысл не «загрязнять», модуль со многими «свободными функциями», и лучше использовать статический метод, чем полагаться на плохой стиль смешивания классов и функций defs вместе в коде, чтобы показать, что они «связаны», – MestreLion 3 May 2012 в 10:55
  • 5
    @unutbu: Вы должны, однако, удалить эту цитату Guido: это был из ранней версии заметок о выпуске python 2.2, и она была изменена в 2.2.3 на: However, class methods are still useful in other places, for example, to program inheritable alternate constructors.. Даже оригинальная цитата очень вводит в заблуждение, поскольку он только сказал, что Распределение python не использует classmethod. Но только потому, что сам python не использует данную функцию, это не значит, что это бесполезная функция. Подумайте о комплексных числах или даже sqrt : сам python тоже не может использовать, но это далеко не бесполезно предлагать – MestreLion 3 May 2012 в 11:44

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

Метод Normal Instance

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

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

', '

, если мы используем метод экземпляра, join on эта строка, чтобы присоединиться к другой итерабельной, она, очевидно, является функцией экземпляра, в дополнение к функции итерируемого списка, ['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.fromkeys(['a', 'b', 'c'])
{'c': None, 'b': None, 'a': None}

Когда мы подклассифицируем dict, мы можем использовать тот же самый метод, который был бы использован в качестве альтернативного конструктора 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 .

39
ответ дан Aaron Hall 16 August 2018 в 03:38
поделиться

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

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()).

Для меня это небольшое нарушение принципа open / closed , так как решение, принятое в 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

10
ответ дан Adam Parkin 16 August 2018 в 03:38
поделиться

@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'>
19
ответ дан Armin Ronacher 16 August 2018 в 03:38
поделиться
  • 1
    В чем проблема с метаклассом? – Armin Ronacher 26 September 2008 в 04:20
  • 2
    В чем преимущества использования метакласса для этого? – Daryl Spitzer 18 January 2009 в 18:51
  • 3
    Один из возможных недостатков метакласса для этого, который мне сразу приходит в голову, заключается в том, что вы не можете вызвать classmethod непосредственно в экземпляре. c = C(); c.foo() вызывает AttributeError, вам нужно будет сделать type(c).foo(). Это также можно считать особенностью - я не могу придумать, почему вы хотите этого. – Aaron Hall♦ 14 June 2016 в 21:57

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

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

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 
656
ответ дан Brian Burns 16 August 2018 в 03:38
поделиться
  • 1
    Статический метод не бесполезен - это способ помещать функцию в класс (потому что он логически принадлежит там), указывая, что он не требует доступа к классу. – Tony Meyer 26 September 2008 в 11:10
  • 2
    Следовательно, только «в основном» бесполезно. Такая организация, а также инъекция зависимостей являются действительными применениями статических методов, но поскольку модули, а не классы, подобные Java, являются основными элементами организации кода в Python, их использование и полезность встречаются редко. – Thomas Wouters 26 September 2008 в 14:40
  • 3
    Что логично в определении метода внутри класса, когда оно не имеет никакого отношения ни к классу, ни к его экземплярам? – Ben James 12 March 2010 в 10:11
  • 4
    Возможно, ради наследования? Статические методы могут быть наследованы и переопределены точно так же, как методы экземпляра и методы класса, и поиск работает как ожидалось (в отличие от Java). Статические методы на самом деле не разрешены статически независимо от того, вызваны ли они классом или экземпляром, поэтому единственное отличие между классом и статическими методами - это неявный первый аргумент. – haridsv 8 April 2010 в 02:32
  • 5
    Они также создают более чистое пространство имен и упрощают понимание функции, которые имеют какое-то отношение к классу. – Imbrondir 22 August 2011 в 12:58

метод класса vs статический метод в 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.
  • Статический метод также является методом, связанным с классом, а не с объектом класса.
  • Статический метод не может получить доступ или изменить состояние класса.
  • Он присутствует в классе, потому что имеет смысл, чтобы метод присутствовал в классе.

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

  • Метод класса принимает 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

Ссылка

4
ответ дан Chirag Maliwal 16 August 2018 в 03:38
поделиться

Я начал изучать язык программирования с помощью 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")
7
ответ дан David Collins 16 August 2018 в 03: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
45
ответ дан Du D. 16 August 2018 в 03:38
поделиться
  • 1
    Жаль, что ваш статический метод на самом деле делает доступ к переменной класса. Может быть, вы можете улучшить свой пример. – Cilyan 1 July 2016 в 17:25

В Python класс метод получает класс как неявный первый аргумент. Класс экземпляра объекта неявно передается как первый аргумент. Это может быть полезно, когда вы хотите, чтобы этот метод являлся фабрикой класса, поскольку он получает фактический класс (который называется методом) в качестве первого аргумента, можно создать экземпляр правого класса, даже если это также относится к подклассам.

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

class Test(object):
    def foo(self, a):
        print "testing (%s,%s)"%(self,a)

    @classmethod
    def foo_classmethod(cls, a):
        print "testing foo_classmethod(%s,%s)"%(cls,a)

    @staticmethod
    def foo_staticmethod(a):
        print "testing foo_staticmethod(%s)"%a

test = Test()

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

6
ответ дан Green Harry 16 August 2018 в 03:38
поделиться

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

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

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

1
ответ дан JawSaw 16 August 2018 в 03:38
поделиться

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

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

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

27
ответ дан Jens Timmerman 16 August 2018 в 03:38
поделиться

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

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

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

  • Он локализует имя функции в классеscope
  • . Он перемещает код функции ближе к тому, где он используется
  • Более удобно импортировать по сравнению с функциями уровня модуля, так как каждый метод не нужно специально импортировать
    @staticmethod
    def some_static_method(*args, **kwds):
        pass
    

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

  • Функции, которые имеют первый аргумент как имя класса.
  • Может быть вызван как с помощью класса, так и с экземпляром.
  • Они создаются с помощью встроенной функции classmethod.
     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass
    
23
ответ дан Jonathan B. 16 August 2018 в 03:38
поделиться

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

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

-5
ответ дан Keith Pinson 16 August 2018 в 03:38
поделиться
  • 1
    «В противном случае, похоже, не функционирует функция»: не строго верно. См. Выше обсуждение. – Keith Pinson 17 December 2012 в 21:46

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

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

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

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

  • Заводские методы , которые используются для создания экземпляр для класса, использующий, например, некоторую предварительную обработку.
  • Статические методы, вызывающие статические методы : если вы разбиваете статические методы несколькими статическими методами, вы не должны hard-code имя класса, но используйте методы класса
17
ответ дан MarianD 16 August 2018 в 03:38
поделиться
  • 1
    Спасибо @zangw - унаследованная неизменность статической функции - ключевое различие, которое кажется – barry_allen 2 May 2018 в 03:38

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

@classmethod

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

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

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

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

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

@staticmethod

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

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

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

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

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

76
ответ дан me_and 16 August 2018 в 03:38
поделиться

Мой вклад демонстрирует разницу между методами @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)
'''
"""
0
ответ дан Michael Swartz 16 August 2018 в 03:38
поделиться

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

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

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

26
ответ дан Nathan Tregillus 16 August 2018 в 03:38
поделиться

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

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- Статический метод не может вызвать метод self, но может вызывать другие static и classmethod

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

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

8
ответ дан Rizwan Mumtaz 16 August 2018 в 03:38
поделиться

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

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

Разница: класс-метод получит сам класс как первый аргумент, в то время как 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',)
5
ответ дан Selva 16 August 2018 в 03:38
поделиться

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

110
ответ дан Tadeck 16 August 2018 в 03:38
поделиться

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

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

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

56
ответ дан Tom Neyland 16 August 2018 в 03:38
поделиться
  • 1
    Значит ли это, что с помощью staticmethod я всегда привязан к классу Parent, а с помощью метода class я привязываю класс, объявляющий classmethod (в данном случае подкласс)? – Mohan Gulati 3 November 2009 в 20:06
  • 2
    Нет. Используя статический метод, вы не связаны вообще; нет неявного первого параметра. Используя классный метод, вы получаете как неявный первый параметр класс, к которому вы вызвали метод (если вы вызывали его непосредственно в классе), или класс экземпляра, на который вы вызвали метод (если вы его вызывали в экземпляре). – Matt Anderson 3 November 2009 в 20:18
  • 3
    Можно было бы немного расшифровать, чтобы показать, что, имея класс в качестве первого аргумента, методы класса имеют прямой доступ к другим атрибутам и методам класса, тогда как статические методы этого не делают (для этого им потребуется жестко указать MyClass.attr) – MestreLion 3 May 2012 в 11:01

Методы класса, как следует из названия, используются для внесения изменений в классы, а не в объекты. Чтобы внести изменения в классы, они будут изменять атрибуты класса (а не атрибуты объекта), поскольку именно так вы обновляете классы. Это причина, по которой методы класса принимают класс (условно обозначаемый «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."
1
ответ дан Tushar Vazirani 16 August 2018 в 03:38
поделиться

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

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

16
ответ дан Tushar.PUCSD 16 August 2018 в 03:38
поделиться

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

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

3
ответ дан vijay 16 August 2018 в 03:38
поделиться
#!/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()
-4
ответ дан Zuckonit 16 August 2018 в 03:38
поделиться
  • 1
    Возможно, объяснение или некоторые комментарии, объясняющие, что делает код, улучшат этот ответ. – mgthomas99 19 January 2018 в 10:50
Другие вопросы по тегам:

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