Home > Net >  Python initialise class variable with call of recursive static method [closed]
Python initialise class variable with call of recursive static method [closed]

Time:09-22

so right now I am working on a Tesseract class that has a class attribute that calls a function called get_relative_path.

Due to all of the pdf2image and images to string transformation, I save all these files in different folders. But since I don't know the absolute path of all the users I tried to get the relative path depending on the name of the project.

And since I inherit this Tesseract class due to the experimental phase. I want to have the relative base path persistent. I could just implement it in my __init__() But I read in that post that it seems to be more persistent to use class attributes.

The function I wrote is recursive and does what I expect.

class Tesseract():
    @staticmethod
    def get_relpath_to_folder(folder_name, start_path = '.'):
       for root, dirs, files in os.walk(start_path, topdown=True):
          if folder_name in dirs:
             return os.path.relpath(os.path.join(root,folder_name))
       return Tesseract.get_relpath_to_folder(folder_name, os.path.join('..',start_path ))
   
    rel_path = get_relpath_to_folder(folder_name)

My problem is how do I initialize the class variable with a method.

I tried:

  • making the method static

    • TypeError: staticmethod object is not callable
  • making the method class method

    • TypeError: classmethod object is not callable
    • class Tesseract():
          @classmethod
          def get_relpath_to_folder(cls, folder_name, start_path = '.'):
              for root, dirs, files in os.walk(start_path, topdown=True):
                  if folder_name in dirs:
                      return os.path.relpath(os.path.join(root,folder_name))
              return cls.get_relpath_to_folder(folder_name, os.path.join('..',start_path ))
          rel_path = get_relpath_to_folder(folder_name)
      
  • call the method as simple function without any decorators

    • NameError: name get_relpath_to_folder is not defined
    • class Tesseract():
          def get_relpath_to_folder(folder_name, start_path = '.'):
              for root, dirs, files in os.walk(start_path, topdown=True):
                  if folder_name in dirs:
                      return os.path.relpath(os.path.join(root,folder_name))
              return get_relpath_to_folder(folder_name, os.path.join('..',start_path ))
          rel_path = get_relpath_to_folder(folder_name)
      
  • putting the class variable above and below the method

    • NameError: name get_relpath_to_folder is not defined

So what is the best solution here?

I explicitly want to use class variable because that how I make the rel_path persistent for all objects

CodePudding user response:

The class attribute (not a variable) is evaluated when the class is defined. That is most definitely not what you want to do.

Maybe you want to pass in folder_name to the __init__() method and set the attribute there?

CodePudding user response:

I don't understand all the context, but your question

how do I initialize the class variable with a method.

can be answered: You could use __class__ to refer to a class of an instance.

class SomeClass:
    def set_class_var_from_instance(self, value):
        self.__class__.class_var = value


some_instance = SomeClass()
another_instance = SomeClass()
some_instance.set_class_var_from_instance(1)
assert another_instance.class_var == 1
assert SomeClass.class_var == 1

Another option is to use a @classmethod on the class and set it on the class:

class SomeClass:
    @classmethod
    def set_class_var(cls, value):
         cls.class_var = value

SomeClass.set_class_var(1)
some_instance = SomeClass()
assert some_instance.class_var == 1

If you want a class variable that is dynamic, but set on the class, you actually want different classes for different scenarios. You can get this by using a factory function to create your class with the class variable:

def factory(value):
     class _SomeClass:
         class_var = value

     return _SomeClass

SomeClassWithOne = factory(1)
some_instance_with_one = SomeClassWithOne()
assert SomeClassWithOne.class_var == 1
assert some_instance_with_one.class_var == 1
  • Related