pythonclasspython-winshell

Is using a class justified for storing variables that are needed in multiple functions?


I'm writing a python script, and one of its features should be that it automatically adds itself to the windows startup folder.

Now I wrote a few functions which would do that for me, but they all rely on multiple variables which shouldn't change after the initial assignment. But I'm not sure where to store them.

This is the code snippet:

def write_shortcut():
    autostart_folder = winshell.startup()
    path = os.path.abspath(__file__)
    target_folder = autostart_folder + r"\proxy-changer.lnk"
    working_directory = path.replace(r'\proxy-changer.pyw', '')

    with winshell.shortcut() as shortcut:
        shortcut.path = path
        shortcut.working_directory = working_directory
        shortcut.description = "Shortcut to the proxy-changer script"
        shortcut.write(target_folder)

def del_shortcut():
    os.remove(target_folder)

def check_shortcut():
    if (config.getboolean('DEFAULT','RunOnStartup') == 1 and not
        os.path.islink(target_folder)):
        write_shortcut()
    elif (config.getboolean('DEFAULT','RunOnStartup') == 0 and
          os.path.islink(target_folder)):
        del_shortcut()
    else:
        pass

Line 2 to 5 are the variables I'm talking about. Currently they are in the first function, but the others then cant access them. Now I know that classes exist and variables inside a class are accessible for all methods inside the class, but I'm not sure whether that is the right way, because it would only contain a single object, instead of multiple.

Outside the functions, before even defining them, doesn't look very clean either. And I'm not sure about making them global.

I think I understand classes generally, but not everything, so If it's obvious that a class would be the right way then I'm sorry. I just heard that classes are often used when not needed (Stop writing classes!), so I'm trying to avoid to make the same mistake. I'm a python beginner, feel free to criticize my code-style or tell me where I'm wrong/could improve it.

Thanks in advance.


Solution

  • It is perfectly fine to have constants as globals of your module/script. Note that it is idiomatic to use UPPER_CASE names for constants.

    Constants PEP8

    Constants are usually defined on a module level and written in all capital letters with underscores separating words. Examples include MAX_OVERFLOW and TOTAL.

    For example, you would define the constants ahead of your functions:

    PATH = os.path.abspath(__file__)
    TARGET_FOLDER = winshell.startup() + r"\proxy-changer.lnk"
    WORKING_DIRECTORY = os.path.dirname(PATH)
    
    def write_shortcut():
        with winshell.shortcut() as shortcut:
            shortcut.path = PATH
            shortcut.working_directory = WORKING_DIRECTORY
            shortcut.description = "Shortcut to the proxy-changer script"
            shortcut.write(TARGET_FOLDER)
    
    def del_shortcut():
        os.remove(TARGET_FOLDER)
    

    Using a class does not give you any advantage. Downsides are that it obscures your intention, it is usually slower, and it fails to provide the functionality generally associated with classes.

    The most straightforward approach is to add constants as class attributes:

    class Constants:
        path = os.path.abspath(__file__)
        target_folder = winshell.startup() + r"\proxy-changer.lnk"
        working_directory = os.path.dirname(path)
    
    def del_shortcut():
        os.remove(Constants.target_folder)
    

    Note that Constants behaves exactly like a module with globals, except that it still has all the now-useless capabilities of a class. For example, while Constants can be instantiated, this is completely meaningless as instances have neither state nor methods.