Leonick
Leonick

Reputation: 75

Classes in python: IDE said Instance attributes defined outside __init__: Everything works, but can't make it work in __init__

This is my first program after a bunch of small tutorials, and my file explorer works wonderfully. Did some custom icons, thumbnail for images, and I can scroll, multyselect stuff and browse with my icons. Originally it took 3.2 seconds to open/resize/blend-paste/display 81 pictures(100x100), and managed to bring it to 1.5 seconds. Multithreading will come soon :) I got rid of all my globals, to learn it the proper way, and now I want to understand classes more, I am happy that I made it work anyhow, but what is the correct way to initialize it in init?

I create an instance with:

folder_left = Folder(folder_left_settings.last_directory)

when I change the Folder:

folder_left.elements_create(values["-FOLDER-"])
folder_left.directory = values["-FOLDER-"]
folder_left_settings.last_directory = values["-FOLDER-"]
folder_left_settings.write_to_ini()
class Folder:
    def __init__(self, directory):
        self.directory = directory
        self.elements_create(directory)

    def elements_create(self, directory):
        self.element_name = []
        self.element_image_data = []
        self.element_is_selected = []
        self.element_is_type = []
        self.list_of_indexes_marked_elements = []
        if directory:
            for file in os.listdir(directory):
                if os.path.isdir(os.path.join(directory,file)):
                    self.element_name.append(file)
                    self.element_is_selected.append(False)
                    self.element_image_data.append(graphics_FolderIcon)
                    self.element_is_type.append("Icon")
                if file.endswith((".gif", ".png", ".jpg")):
                    self.element_name.append(file)
                    self.element_is_selected.append(False)
                    self.element_is_type.append("Image")
                    try:
                        self.element_image_data.append(
                            image.convert_to_bytes(os.path.join(directory, file), (100, 100), fill_blanc_color=(90, 105, 121)))
                    except:
                        sg.popup(f"Error reading Image:{self.element_name}")
                        self.element_image_data.append(empty_image)

this tread Instance attribute attribute_name defined outside __init__ suggested to initialize them with None in init

I tried several combinations of:

def __init__(self, directory ***self.element_name=None***):
***self.element_name=None***
***self.element_name = []***
***self.element_name = element_name***

    def elements_create(self, directory):
        ***self.element_name = []***

of course not all together, just the combinations(with and without)....nothing works, and my elements end up beeing None, or other exceptions. I know that I can do everything INSIDE ini directly and just overwrite create my instance if the folder changes, but I thought this would be better and proper. THX ALOT!!!

(I don't really understand the return 2nd answer with return as solution. It would make it pretty unreadable if I cannot append directly to the lists, since if understanding correctly, I would use placeholder objects in my method, so I can return all in one line. There must be a simple solution I don't see.)

Upvotes: 0

Views: 457

Answers (1)

João Bonfim
João Bonfim

Reputation: 51

This IDE recommendation is for organizing your code only, and should not affect how it works. However, it exists to remind you to put just the behavior necessary for instantiate your class in __init__, if your class has data that does not depend on initialization you can put it before __init__. For example:

class Folder:
    element_name = []
    element_image_data = []
    element_is_selected = []
    element_is_type = []
    list_of_indexes_marked_elements = []

    def __init__(self, directory):
        self.directory = directory
        self.elements_create(directory)

    def elements_create(self, directory):
        ...

Or you can also take this other approach, which may be more suitable in some cases:

class Folder:
    def __init__(self, directory):
        self.directory = directory

    @classmethod
    def create_instance(cls, directory):
        folder = cls(directory)
        folder.element_name = []
        folder.element_image_data = []
        folder.element_is_selected = []
        folder.element_is_type = []
        folder.list_of_indexes_marked_elements = []
        return folder

folder = Folder.create_instance("directory")
print(dir(folder))

Output:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'create_instance', 'directory', 'element_image_data', 'element_is_selected', 'element_is_type', 'element_name', 'list_of_indexes_marked_elements']

Upvotes: 1

Related Questions