Вызов staticmethod внутри инициализации контейнеров уровня класса

Учитывая следующий пример класса:

class Foo:

    def aStaticMethod():
        return "aStaticMethod"

    aVariable = staticmethod(aStaticMethod)
    aTuple = (staticmethod(aStaticMethod),)
    aList = [staticmethod(aStaticMethod)]

print Foo.aVariable()
print Foo.aTuple[0]()
print Foo.aList[0]()

Почему вызов aVariable работает правильно, но с aTuple и aList он возвращает ошибку 'staticmethod' object is not callable?

Ответы

Ответ 1

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

Итак, если вы хотите называть это, вы должны сами заполнить детали:

>>> Foo.aTuple[0].__get__(None, Foo)()
'aStaticMethod'

Здесь None передается параметру instance (экземпляр, к которому обращается дескриптор), и Foo передается параметру owner (класс, по которому находится этот экземпляр дескриптора). Это заставляет его возвращать действительную вызываемую функцию:

>>> Foo.aTuple[0].__get__(None, Foo)
<function aStaticMethod at 0xb776daac>