如何从Python中的类内部访问ClassMethod

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

我想在Python中创建一个类,它首先管理所有静态成员。这些成员应该在类的定义过程中被初始化。由于稍后需要重新初始化静态成员,因此我将把此代码放入ClassMethod。

我的问题是:如何从类内调用这个类方法?

1
2
3
4
5
6
7
8
9
10
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

感谢您的帮助!

事先谢谢,沃尔克


在您的示例中执行x=10时,不仅类不存在,而且类方法也不存在。

在python中执行从上到下。如果x=10在classmethod之上,则此时无法访问classmethod,因为它尚未定义。

即使可以运行ClassMethod,也没关系,因为类还不存在,所以ClassMethod不能引用它。直到整个类块运行之后才创建类,因此当您在类块中时,没有类。

如果您想考虑一些类初始化,以便稍后按照您描述的方式重新运行它,请使用类修饰器。类修饰器在创建类之后运行,因此它可以调用ClassMethod。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
>>> 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


通过同样附加类名来调用类方法:

1
class.method

在您的代码中,这样的内容应该足够:

1
Test.static_init()

你也可以这样做:

1
static_init(Test)

要在类内调用它,请让代码执行以下操作:

1
Test.static_init()

我的工作代码:

1
2
3
4
5
6
7
8
class Test(object):

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

    def another_method(self):
        Test.static_method()

Test().another_method()返回Hello


你不能在theclass定义中调用aclassmethod,因为类还没有完全定义,所以没有什么可以作为第一个cls参数传递方法……一个典型的鸡和蛋问题。但是,您可以通过在元类中重载the__new__()方法,并在创建类之后从中调用class method来解决这个限制,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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

输出:

1
2
Hello
10

这次仔细阅读你的问题后,我可以想出两个解决办法。第一个是应用Borg设计模式。第二种方法是放弃类方法,改用模块级函数。这似乎可以解决您的问题:

1
2
3
4
5
6
7
8
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

旧的错误答案:

下面是一个例子,我希望它有助于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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的答案更好:在访问类方法时使用类名。它使您的代码不那么晦涩。