Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refer to class methods when defining class variables in Python?

I have the following class and class variables:

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

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

However, the interpreter says that run_class_method isn't defined. Using MyClass.run_class_method() doesn't work either. Coming from a java background, I don't understand why this doesn't work. So, how can I fix it?

Additionally, I discovered that this works if I define class variables at the end of the class. Is this considered bad practice in python?

like image 253
Yang K Avatar asked Dec 17 '22 18:12

Yang K


1 Answers

Class body in python is an executable context, not like Java that only contains declaration. What this ultimately means is that sequence of execution is important within a class definition.

To quote the documentation:

class definition is an executable statement.

...

The class’s suite is then executed in a new execution frame (see Naming and binding), using a newly created local namespace and the original global namespace. (Usually, the suite contains mostly function definitions.) When the class’s suite finishes execution, its execution frame is discarded but its local namespace is saved. [4] A class object is then created using the inheritance list for the base classes and the saved local namespace for the attribute dictionary. The class name is bound to this class object in the original local namespace.

Some more lengthier explanations.

If you want to call a function to define a class variable, you can do it with one of these ways:

  1. use staticmethod:

    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__()
    
  2. or define it as a standalone function:

    def run_method():
        return "ran method"
    
    class MyClass:
        class_var_1 = "a"
        class_var_2 = run_method()
    
        # optional
        run_method = staticmethod(run_method)
    
  3. or access the original function with __func__ and provide a dummy cls value:

    class MyClass:
        @classmethod
        def run_class_method(cls):
            return "ran class method"
    
        class_var_1 = "a"
        class_var_2 = run_class_method.__func__(object())
    
  4. or set the class variables after class creation:

    class MyClass:
        @classmethod
        def run_class_method(cls):
            return "ran class method"
    
        class_var_1 = "a"
    
    MyClass.class_var_2 = MyClass.run_class_method()
    
like image 194
Lie Ryan Avatar answered Feb 05 '23 17:02

Lie Ryan