Home > Net >  Is there a better way to change how a function works depending on inputs?
Is there a better way to change how a function works depending on inputs?

Time:09-01

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:

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

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. I 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")
  • Related