How can I access a classmethod from inside a class in Python

半腔热情 提交于 2019-11-27 02:36:16

问题


I would like to create a class in Python that manages above all static members. These members should be initiliazed during definition of the class already. Due to the fact that there will be the requirement to reinitialize the static members later on I would put this code into a classmethod.

My question: How can I call this classmethod from inside the class?

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

Any help is appreciated!

Thanks in advance, Volker


回答1:


At the time that x=10 is executed in your example, not only does the class not exist, but the classmethod doesn't exist either.

Execution in Python goes top to bottom. If x=10 is above the classmethod, there is no way you can access the classmethod at that point, because it hasn't been defined yet.

Even if you could run the classmethod, it wouldn't matter, because the class doesn't exist yet, so the classmethod couldn't refer to it. The class is not created until after the entire class block runs, so while you're inside the class block, there's no class.

If you want to factor out some class initialization so you can re-run it later in the way you describe, use a class decorator. The class decorator runs after the class is created, so it can call the classmethod just fine.

>>> 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:


You call a class method by appending the class name likewise:

class.method

In your code something like this should suffice:

Test.static_init()

You could also do this:

static_init(Test)

To call it inside your class, have your code do this:

Test.static_init()

My working code:

class Test(object):

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

    def another_method(self):
        Test.static_method()

and Test().another_method() returns Hello




回答3:


You can't call aclassmethodin theclassdefinition because the class hasn't been fully defined yet, so there's nothing to pass the method as its firstclsargument...a classic chicken-and-egg problem. However you can work around this limitation by overloading the__new__()method in a metaclass, and calling the classmethod from there after the class has been created as illustrated below:

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

Output:

Hello
10



回答4:


After re-reading your question carefully this time I can think of two solutions. The first one is to apply the Borg design pattern. The second one is to discard the class method and use a module level function instead. This appears to solve your problem:

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

Old, incorrect answer:

Here's an example, I hope it helps:

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

Anyway, NlightNFotis's answer is a better one: use the class name when accessing the class methods. It makes your code less obscure.



来源:https://stackoverflow.com/questions/13900515/how-can-i-access-a-classmethod-from-inside-a-class-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!