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
- TypeError:
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)
- TypeError:
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)
- NameError: name
putting the class variable above and below the method
- NameError: name
get_relpath_to_folder
is not defined
- NameError: name
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