Как я могу получить доступ к classmethod изнутри класса в Python - программирование
Подтвердить что ты не робот

Как я могу получить доступ к classmethod изнутри класса в Python

Я хотел бы создать класс в Python, который управляет прежде всего статическими членами. Эти члены должны быть инициализированы во время определения класса уже. В связи с тем, что в дальнейшем будет требоваться повторная инициализация статических членов, я бы поставил этот код в классный метод.

Мой вопрос: как я могу вызвать этот класс из класса?

class Test():
    # static member
    x = None
    # HERE I WOULD LOVE TO CALL SOMEHOW static_init!

    # initialize static member in classmethod, so that it can be 
    #reinitialized later on again    
    @classmethod
    def static_init(cls):
        cls.x = 10

Любая помощь приветствуется!

Спасибо заранее, Volker

4b9b3361

Ответ 1

В то время, когда x=10 выполняется в вашем примере, класс не существует, но метод class тоже не существует.

Выполнение в Python идет сверху вниз. Если x=10 находится выше метода класса, вы не можете получить доступ к методу class в этой точке, потому что он еще не определен.

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

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

>>> def deco(cls):
...     cls.initStuff()
...     return cls
>>> @deco
... class Foo(object):
...     x = 10
...     
...     @classmethod
...     def initStuff(cls):
...         cls.x = 88
>>> Foo.x
88
>>> Foo.x = 10
>>> Foo.x
10
>>> Foo.initStuff() # reinitialize
>>> Foo.x
88

Ответ 2

Вы вызываете метод класса, добавляя также имя класса:

class.method

В вашем коде должно быть достаточно:

Test.static_init()

Вы также можете сделать это:

static_init(Test)

Чтобы вызвать его внутри своего класса, выполните свой код:

Test.static_init()

Мой рабочий код:

class Test(object):

    @classmethod
    def static_method(cls):
        print("Hello")

    def another_method(self):
        Test.static_method()

и Test().another_method() возвращает Hello

Ответ 3

После повторного чтения вашего вопроса , на этот раз я могу представить два решения. Первый - применить шаблон дизайна Borg. Второй способ - отбросить метод класса и вместо этого использовать функцию уровня модуля. Это, похоже, решает вашу проблему:

def _test_static_init(value):
    return value, value * 2

class Test:
    x, y = _test_static_init(20)

if __name__ == "__main__":
    print Test.x, Test.y

Старый, неправильный ответ:

Вот пример, я надеюсь, что это поможет:

class Test:
    x = None

    @classmethod
    def set_x_class(cls, value):
        Test.x = value

    def set_x_self(self):
        self.__class__.set_x_class(10)

if __name__ == "__main__":
    obj = Test()
    print Test.x
    obj.set_x_self()
    print Test.x
    obj.__class__.set_x_class(15)
    print Test.x

В любом случае, ответ NlightNFotis является лучшим: используйте имя класса при доступе к методам класса. Это делает ваш код менее неясным.

Ответ 4

Вы не можете вызывать classmethod в определении class, потому что класс еще не определен полностью, поэтому не нужно передавать метод в качестве его первого аргумента cls... классического цыпленка- и-яйца. Однако вы можете обойти это ограничение, перегрузив метод __new__() в метаклассе и вызывая метод класса оттуда после создания класса, как показано ниже:

class Test(object):
    # nested metaclass definition
    class __metaclass__(type):
        def __new__(mcl, classname, bases, classdict):
            cls = type.__new__(mcl, classname, bases, classdict)  # creates class
            cls.static_init()  # call the classmethod
            return cls

    x = None

    @classmethod
    def static_init(cls):  # called by metaclass when class is defined
        print("Hello")
        cls.x = 10

print Test.x

Вывод:

Hello
10