If else - if the code looks ugly by any clean solution?

I have about 20 functions (is_func1, is_fucn2, is_func3 ...) returning boolean

I am assuming there is only one function that returns true and I want that!

I am doing:

if is_func1(param1, param2):
    # I pass 1 to following
    abc(1) # I pass 1
    some_list.append(1)
elif is_func2(param1, param2):
    # I pass 2 to following
    abc(2) # I pass 1
    some_list.append(2)
...
.
.
elif is_func20(param1, param2):
...

      

Note: param1 and param2 are different for each, abc and some_list take parameters depending on the function.

The code looks great and there is repetition when calling abc and some_list, I can pull this login in the function! but is there any other cleanup solution?

I can think of putting the functions in a data structure and a loop to call them.

+2


a source to share


9 replies


What about



functionList = [is_func1, is_func2, ..., is_func20]
for index, func in enumerate(functionList):
    if(func(param1, param2)):
        abc(index+1)
        some_list.append(index+1)
        break

      

+4


a source


I can think of putting the functions in a data structure and a loop to call them.

Yes, you probably should, as your code needs to be refactored
and data-centric design is a good choice.



An example similar to BlueRaja's answer ,

# arg1, arg2 and ret can have any values on each record
data = ((isfunc1, arg1, arg2, ret),
 (isfunc2, arg1, arg2, ret),
 (isfunc3, arg1, arg2, ret),
  ...)

for d in data:
    if d[0](d[1], d[2]):
        abc(d[3])
        some_list.append(d[3])
        break

      

+2


a source


If each branch of your event dispatcher is actually different, then there is simply no way to get around the order in which the individual branch handlers are written, and there is no way to bypass polling for different cases and select a branch.

+1


a source


Try the following:

value = 1 if is_func1(param1, param2) else \
        2 if is_func2(param1x, param2x) else \
        ... else \
        20 if is_func20(param1z, param2z) else 0

abc(value)
some_list.append(value)

      

Keep in mind that this statement was floated together using various websites as a reference for the Python syntax, so please don't shoot me if it doesn't compile.

The main point is to create one value corresponding to a function called (1 for is_func1

, 2 for is_func2

, etc.), then use that value in the functions abc

and some_list.append

. Based on what I've been able to read about Python expression boolean, this should properly short-circuit the evaluation so that functions will stop being called as soon as one evaluates to true.

+1


a source


This is a good use case for Chain of Responsibility .

I know how to give an example to objects, not functions, so I'll do this:

class HandleWithFunc1
   def __init__(self, otherHandler):
      self.otherHandler = otherHandler

   def Handle(param1, param2):
     if ( should I handle with func1? ):
          #Handle with func1
          return
     if otherHandler == None:
        raise "Nobody handled the call!"

     otherHandler.Handle(param1, param2)

class HandleWithFunc2:
   def __init__(self, otherHandler):
      self.otherHandler = otherHandler

   def Handle(param1, param2):
     if ( should I handle with func1? ):
          #Handle with func1
          return
     if otherHandler == None:
        raise "Nobody handled the call!"

     otherHandler.Handle(param1, param2)

      

So, you create all your classes as a chain:

handle = HandleWithFunc1(HandleWithFunc2())

      

then

handle.Handle(param1, param2)

      

This code is subject to refactoring, here only for illustration of use

+1


a source


I modified BlueRaja's answer for different parameters ...

function_list = {is_func01: (pa1, pa2, ...),
                 is_func02: (pa1, pa2, pa3, ...), 
                 ....
                 is_func20: (pa1, ...)}

for func, pa_list in function_list.items:
    if(func(*pa_list)):
        abc(pa_list_dependent_parameters)
        some_list.append(pa_list_dependent_parameters)
        break

      

I don't understand why this shouldn't work.

+1


a source


I haven't used python before, but can you reference functions by variable?

If so, you can create an enum with entries representing each function, check all the functions in the loop, and set the variable in the function enum to "true".

Then you can make a switch statement to enumerate.

However, this doesn't clean up the code much: when you have n options and need to collapse to the desired one, you need n blocks of code to process it.

0


a source


I'm not sure if this would be cleaner, but I think it's a pretty interesting solution.

First of all, you must define a new function, let it be semi_func

, that will call abc

and some_list.append

make the code DRY.

Then set a new variable to act as the binary of all boolean functions, so is_func1 is the 20th bit, is_func2 is 19, and so on. 32 bits of integer type should be sufficient to process all 20 results.

When setting the value of this result variable, you must use shift left to add new functions:

result = is_func1(param1, param2) << 1
result = (result | is_func2(param1, param2)) << 1
...
result = (result | is_func20(param1, param2))

      

For easier access, define new constants such as

IS_FUNC20_TRUE = 1
IS_FUNC19_TRUE = 2
IS_FUNC18_TRUE = 4
... values should be powers of 2

      

And at the end, use a switch / sase statement to call semi_func

.

0


a source


I know that I will be cheated for being offtopic, but still. If you find something that can be done with standard control constructs, then you need to use another language, such as Common Lisp, which allows macros, essentially lets you create your own control constructors. (Having recently discovered anaphoric macros, I just have to recommend it.)

This particular case would be a perfect example where a macro could help, but only assuming you are doing this in multiple places in your code, otherwise it probably shouldn't be improved at all. And in fact, Common Lisp already has such a macro, it's called cond .

Anyway, in Python, I think you should go with a list of functions and a loop.

-3


a source







All Articles