Home > Software engineering >  Is there a simpler way to change how a function works depending on inputs?
Is there a simpler way to change how a function works depending on inputs?

Time:09-02

I have a function that I want to do/output something different depending on what inputs I give it. I've made something useful with if else logic but not elegant and I suspect there might be a shorter/more elegant way of doing it. What are the alternatives to the if else on None methods I've made?

e.g.,

def foo (a=None, b=None, c=None):
    if a is None:
        raise ValueError("a cannot be None!")
    elif all([b is None, c is None]):
        x = operations
        return x
    elif c is None:
        x = operations
        y = operations
        return x, y
    elif b is None:
        x = operations
        z = operations
        return x, z
    elif all([b is not None, c is not None]):
        x = operations
        y = operations
        z = operations
        return x, y, z

CodePudding user response:

It depends on what exactly you mean by "better" and what you are trying to do inside your ifs and elifs but I myself am not a big fan of the code style in your example either. It can become hard to read and maintain.

There are languages that make this kind of thing easy, but unfortunately Python is not one of them. However, there are a few ways that I think are "better", depending on what you are trying to do.

  1. Lots of elifs:
def show_food_description(food):
   if food == "apple":
      print("It's red and sweet")
   elif food == "banana":
      print("It's long and yellow")
   elif food == "kiwi":
      print("It's green and hairy")
   else:
      print("This food is unknown")

alternative:

def show_food_description(food):
   descriptions = {
      "apple": "It's red and sweet",
      "banana": "It's long and yellow",
      "kiwi": "It's green and hairy"
   }
   print(descriptions.get(food, "This food is unknown"))
  1. Testing for equality with more than one value:
food = "apple"

if food == "apple" or food == "banana" or food == "kiwi":
   print("It's a fruit!")

alternative:

food = "apple"
fruits = ["apple", "banana", "kiwi"]

if food in fruits:
   print("It's a fruit!")
  1. Execute different function
def add_one(x):
   return x   1

def add_two(x):
   return x   2

def add_three(x):
   return x   3


def perform_operation(x, operation):
   if operation == "add_one":
      return add_one(x)
   if operation == "add_two":
      return add_two(x)
   if operation == "add_three":
      return add_three(x)
   else:
      raise Exception("Unknown operation")

alternative:

def add_one(x):
   return x   1

def add_two(x):
   return x   2

def add_three(x):
   return x   3

def unknown_operation(x):
   raise Exception("Unknown operation")

def perform_operation(x, operation):
   operations = {
      "add_one": add_one,
      "add_two": add_two,
      "add_three": add_three
   }

   selected_operation = operations.get(operation, unknown_operation)
   return selected_operation(x)
   

It is also worth mentioning that in Python 3.10, there is a match statement available that is similar to switch statements in other languages. Here is an example on how to use it:

language = "Python"

match language:
   case "C": print("It's C")
   case "Python": print("It's Python")
   case _: print("It doesn't matter")

CodePudding user response:

If you have Python 3.10 installed you can use the match-case. Please refer to PEP 634

Honestly code readability is very subjective, if you were looking for something like a switch-case logic in python, Your code would look like -

def foo (a=None, b=None, c=None):
  match a, b, c:
    # Add all your cases
    case None, None, _:
      # Do Your Operations and Return
      return
    case other:
      print("Other Cases")

This is one of the best features that got released with 3.10. Hope this helps you.

CodePudding user response:

If I understand your problem, you might find the new pattern matching syntax to be what you want (requires python >= 3.10, spec in PEP634, tutorial in PEP636).

def foo(a=None, b=None, c=None):
    match a, b, c:
        case a_, None, None:
            r = 1 * a_
        case None, b_, None:
            r = 2 * b_
        # add more patterns here
        case _:
            r = None
    return r

foo(a=1)  # 1
foo(b=5)  # 10
foo(a=0, b=0)  # None # no pattern for a and b
foo(c=8)  # None # no pattern for c

NB. the same is achievable with if/elif/else.

def bar(a=None, b=None, c=None):
    if a is not None and b is None and c is None:
        r = 1 * a
    elif a is None and b is not None and c is None:
        r = 2 * b
    # add more elifs here
    else:
        r = None
    return r
  • Related