Значение описания объекта staticmethod? - PullRequest
1 голос
/ 09 января 2020

На практике я понимаю @staticmethod декоратор. Но ошибка в насмешке метода stati c привела меня в семантическую кроличью нору Python. Это описание в разделе стандартной иерархии типов меня сбивает с толку:

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

Конструктор staticmethod() принимает объект функции в качестве единственного аргумента. Как он может обернуть любой другой объект, кроме функционального объекта? Даже если это не сработает, как это имеет смысл?

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

Как неужели объекты метода stati c сами по себе не могут вызываться? Как тогда звонки на эти работы?

Ответы [ 2 ]

2 голосов
/ 09 января 2020

Как можно обернуть любой другой объект, кроме функционального объекта?

Довольно легко.

class Example(object):
    example = staticmethod(5)

print(Example.example) # prints 5

Вы можете передать все, что хотите, в staticmethod Конструктор.

Даже если это не сработает, как это имеет смысл?

Обычно это не так, но staticmethod не проверяет.

Как обычно это обертка вокруг определяемого пользователем объекта метода вместо функционального объекта?

Это не так. Эта часть просто неправильная.

Как получается, что объекты метода stati c сами по себе не могут вызываться? Как тогда работают эти вызовы?

Протокол дескриптора . У объектов метода Stati c есть метод __get__, который возвращает любой объект, который они переносят. Доступ к атрибуту вызывает этот метод __get__ и возвращает то, что возвращает __get__.

2 голосов
/ 09 января 2020

Вы можете видеть, что staticmethod может принимать любой аргумент:

>>> x = staticmethod(3)

и что он действительно не может быть вызван:

>>> x()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable

staticmethod не подходит гораздо больше, чем хранить ссылку на свой аргумент. «Magi c» возникает, когда вы пытаетесь получить доступ к объекту staticmethod как атрибуту объекта class или экземпляру класса. Когда вы это сделаете, вы получите результат метода staticmethod метода __get__, который ... то, что вы изначально обернули.

>>> x.__get__(x)
3

Не беспокойтесь о том, почему мы передали x в качестве аргумента; достаточно сказать, что staticmethod.__get__ в основном игнорирует его аргументы.

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

>>> class Foo(object):
...   @staticmethod
...   def x():
...     pass
...
>>> type(Foo.__dict__['x'])
<type 'staticmethod'>
>>> type(Foo.x)
<type 'function'>

Методы экземпляра работают так же, как и они, потому что function.__get__ возвращает экземпляр method, который в некотором смысле только в первоначальной функции частично применил экземпляр, который вызывает это. Возможно, вы видели, что x.foo() совпадает с type(x).foo(x). причина , которая является истинной, заключается в том, что x.foo сначала разрешается в type(x).foo, что само по себе оценивается в type(x).__dict__['foo'].__get__(x, type(x). Возвращаемое значение function.__get__ в основном является оболочкой для функции foo, но с x, уже предоставленным в качестве первого аргумента.

staticmethod Основная цель - предоставить другой __get__ method.

Кстати, classmethod служит той же цели. classmethod.__get__ возвращает то, что вызывает упакованную функцию с class в качестве первого аргумента, независимо от того, вызываете ли вы метод класса из экземпляра класса или самого класса.

...