简体   繁体   中英

Python - Select function or alter module based on user input during class instantiation

I think posting even a minimal working example of this problem might be messy, so I'm going to outline the problem using pseudocode. I have a module where I have defined a class - let's call it my_class.py. The class methods use a lot of similar code so it made sense to break out these code blocks into functions and put them into a separate module - let's call it functions.py. To clarify, functions.py looks like this:

def dependent(inverted):
    if inverted:
        return this
    else: 
        return that

def func_a():
    do stuff...
    dependent()

def func_b():
    dependent()
    do stuff...

... more functions ...

def func_z()
    do stuff...
    dependent()

and my_class.py looks like this:

from functions import func_a, func_b, func_c

class A():
    def __init__(self, inverted=False):
        self.inverted = inverted

    def method_1(self,):
         do stuff....
         func_a()
         do sfuff ...
         func_b()

    def method_2(self,):
        func_c()

    ... more methods using functions from functions.py

Now, you might be looking at that weird "dependent" function in functions.py and the "inverted" keyword in the class init method. You see, the functions func_a, func_b, ... , func_z in functions.py also reuse a lot of the same code so I put that code in a function named dependent - because functions func_a, func_b, etc. are dependent on it.

Things were looking pretty slick, but then I noticed a corner case I needed to consider. This case is easily accounted for using a Boolean variable named "inverted". The user should specify if the problem is inverted while instantiating the class. The issue is that the only function that directly changes is the dependent function. The other functions, func_a, func_b, etc. will change indirectly since they are dependent on "dependent". Note, the class never actually calls "dependent", only func_a, func_b, etc.

I think I may have painted myself into a corner. I can't think of a clean way to alter or pass the inverted option to the "dependent" function from the class to the module said class is importing. In fact, that process seems circular and dumb.

I have thought of two solutions.

1) Pass self.inverted to func_a, func_b, ..., func_z. So the methods would look like this:

def method_1(self):
    do stuff...
    func_a(self.inverted)
    ...

and func_a, func_b, etc. would look like this:

def func_a(inverted):
    do stuff...
    dependent(inverted)

or 2) create two functions modules with the only difference being one has dependent set to return that and the other has dependent set to return this (the inverted case). Then the class init method would import the corresponding function module based on the inverted argument. Visually:

class A():
    def __init__(self, inverted=False):
        if inverted:
            from functions_inverted.py import func_a, func_b, ...
        else:
            from functions_normal.py import func_a, func_b, ...

I don't like either option since I am repeating a lot of code and it kind of nullifies the original intent of making the code modular and clean. If I had noticed the corner case earlier I likely would have taken a different approach, however, at this point, a significant amount of time has been used getting the code to its current state.

Is there a better solution - one that keeps the code modular and clean - so that I can alter all the functions in functions.py by only passing an option to the function "dependent" when this option is provided during class instantiation? Note that multiple instances of the class may be called/running simultaneously.

Thanks!

Given the last requirement,

Note that multiple instances of the class may be called/running simultaneously.

you can wrap all your functions in a class (they become methods) and make inverted a parameter you pass to every instance of that class. Then you set self.inverted on every instance __init__ , and you check that when running the dependent function (from that instance).

It looks like you have done that at an upper level where it is not needed. You may just instantiate the utility class with the functions there, and change your function calls to use the methods of the instance instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM