python, как вызвать статический метод изнутри тела класса

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

class A:
    @staticmethod
    def foo():
        return 12

     baz = foo()

Но делая это, я получаю сообщение об ошибке:

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

Я нашел способ обойти это:

class A:
    class B:
        @staticmethod
        def foo():
            return 2
baz = B.foo()

Но, например, если я напишу:

class A:
    class B:
        @staticmethod
        def foo():
            return 2

    class C:
        baz = B.foo()

Я также получаю сообщение об ошибке:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in A
  File "<stdin>", line 7, in C
NameError: name 'B' is not defined

Есть ли способ вызвать статические методы внутри класса при его объявлении? Почему 1-й и 3-й примеры кода не работают, а 2-й работает? Как интерпретатор Python обрабатывает такие объявления?


person arrowknee    schedule 06.08.2017    source источник


Ответы (2)


staticmethod — это дескриптор. Дескриптор предоставляет метод __get__(instance, cls), позволяющий получить к нему доступ либо через экземпляр, либо на уровне класса.

Теперь в вашем случае вы хотите вызвать его в строфе класса. Обычно это невозможно, так как ни экземпляр, ни класс еще не доступны. Однако staticmethod в любом случае игнорирует оба, поэтому вы можете использовать следующий довольно неприятный подход для его вызова.

class A:
    @staticmethod
    def foo():
        return 12

    baz = foo.__get__(None, object)()

потом

>>> A.baz
12

Примечание. Единственная причина для передачи object в качестве второго аргумента заключается в том, что staticmethod настаивает на передаче какого-либо класса в качестве второго аргумента.

person donkopotamus    schedule 06.08.2017

Это тоже обходной путь, но он может помочь.

В теле class нельзя ссылаться на создаваемый класс. OTOH декоратор класса получает инициализированный класс, поэтому он может напрямую вызывать его методы.

def add_baz(cls):
    cls.baz = cls.foo()
    return cls 

@add_baz
class A:
    @staticmethod
    def foo():
        return 12
person VPfB    schedule 06.08.2017