В чем разница между class.method class.staticmethod с одинаковыми параметрами?

#python #function #class #static-methods #descriptor

#питон #функция #класс #статические методы #дескриптор #python

Вопрос:

Я написал простой скрипт:

 class A:
    def print1(self):
        print(self)

    @staticmethod
    def print2(thing):
        print(thing)

A.print1('123')
A.print2('123')

print(A.print1)
print(A.print2)
  

И вывод такой:

 123
123
<function A.print1 at 0x7f2f4a1778c8>
<function A.print2 at 0x7f2f4a17b510>
  

Сначала ДА или НЕТ: пока кажется, A.print1 и A.print2 делайте все то же самое по функционалу, верно?

Как код из Python на Github:

 /* Bind a function to an object */
static PyObject *
func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
{
    if (obj == Py_None || obj == NULL) {
        Py_INCREF(func);
        return func;
    }
    return PyMethod_New(func, obj);
}
  

И версия Python StaticMethod из руководства по дескриптору HowTo

 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
  

Во-вторых, ДА или НЕТ: A.print1 и A.print2 все просто получают функцию, очень похожую на print_pure , которая определена ниже, верно?

 def print_pure(thing):
    print(thing)
  

Комментарии:

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

Ответ №1:

Если вы собираетесь вызывать методы из самого класса, как вы делаете в своем коде, «ДА», разницы нет. Однако все начнет отличаться в тот момент, когда вы начнете вызывать эти методы с объектом класса.

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

Метод класса — это функция, которая привязана к самому классу и всегда требует ссылки на сам класс в качестве своего первого параметра.

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

Даже с вашим кодом, если мне это нравится.

 a = A()
a.print2('123') # this will work just fine, since this is a static method
a.print1('123')  # this will give me the TypeError print1() takes 1 positional argument but 2 were given 
  

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