在 Python 中定义类变量时如何引用类方法?

Yan*_*g K 3 python class class-method python-3.x

我有以下类和类变量:

class MyClass:
    class_var_1 = "a"
    class_var_2 = run_class_method()

    @classmethod
    def run_class_method(cls):
        return "ran class method"
Run Code Online (Sandbox Code Playgroud)

但是,解释器说这run_class_method没有定义。使用MyClass.run_class_method()也不行。来自 java 背景,我不明白为什么这不起作用。那么,我该如何解决呢?

此外,我发现如果我在类的末尾定义类变量,这会起作用。这在python中被认为是不好的做法吗?

Lie*_*yan 6

python中的类体是一个可执行的上下文,不像Java那样只包含声明。这最终意味着执行顺序在类定义中很重要。

引用文档:

类定义是一个可执行语句。

...

然后使用新创建的本地命名空间和原始全局命名空间在新的执行框架中执行该类的套件(请参阅命名和绑定)。(通常,套件主要包含函数定义。)当类的套件完成执行时,它的执行帧将被丢弃,但它的本地命名空间会被保存。[4] 然后使用基类的继承列表和为属性字典保存的本地命名空间创建类对象。类名绑定到原始本地命名空间中的这个类对象。

一些更冗长的解释

如果要调用函数来定义类变量,可以使用以下方法之一:

  1. 使用静态方法:

    class MyClass:
        def _run_instance_method():
            return "ran instance method"
        run_instance_method = staticmethod(_run_instance_method)
    
        class_var_1 = "a"
        class_var_2 = _run_instance_method() # or run_instance_method.__func__()
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或将其定义为独立函数:

    def run_method():
        return "ran method"
    
    class MyClass:
        class_var_1 = "a"
        class_var_2 = run_method()
    
        # optional
        run_method = staticmethod(run_method)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 或访问原始函数__func__并提供一个虚拟cls值:

    class MyClass:
        @classmethod
        def run_class_method(cls):
            return "ran class method"
    
        class_var_1 = "a"
        class_var_2 = run_class_method.__func__(object())
    
    Run Code Online (Sandbox Code Playgroud)
  4. 或在类创建后设置类变量:

    class MyClass:
        @classmethod
        def run_class_method(cls):
            return "ran class method"
    
        class_var_1 = "a"
    
    MyClass.class_var_2 = MyClass.run_class_method()
    
    Run Code Online (Sandbox Code Playgroud)


blh*_*ing 3

MyClass当其类属性仍在定义时尚未定义,因此在class_var_2定义时MyClass尚未可供参考。class_var_2您可以通过在定义块之后定义来解决此问题MyClass

class MyClass:
    class_var_1 = "a"

    @classmethod
    def run_class_method(cls):
        return "ran class method"

MyClass.class_var_2 = MyClass.run_class_method()
Run Code Online (Sandbox Code Playgroud)