'What are the advantages/disadvantages of if/else vs if/elif/raise [closed]

I have something similar to this in a pull request:

def my_func(my_var: str) -> str:
    if my_var == 'val1':
        return '1'
    elif my_var == 'val2':
        return '2'
    else:
        raise ValueError('Unsupported value')

The value of my_var is ensured to be either 'val1' or 'val2' in a different place of the code. For that reason, I have been suggested to remove the raise statement and leave only a if/else:

def my_func(my_var: str) -> str:
    if my_var == 'val1':
        return '1'
    else:
        return '2'

The reason given is that the raise is not required as the value is checked in a different place, and it may be confusing/unnecessary.

I don't like that option because:

  1. It is not impossible that the value check of my_var that happens on a different place changes over time, which would make this code to be potentially wrong as it will handle any new values using the else part of the conditional.
  2. It doesn't explicitly state the else value ('val2'), as it would be just an else without equality.

What are other advantages/disadvantages of either case? Are there any better alternatives?

I want more info to decide the best alternative, as this case comes frequently in our code reviews.



Solution 1:[1]

Are there any better alternatives?

If you have variable which can have limited number of values then it might be represented using enum. You need powe to dictate what type of argument your function is accepting in order to use this approach.

It is not impossible that the value check of my_var that happens on a different place changes over time, which would make this code to be potentially wrong as it will handle any new values using the else part of the conditional.

You need to unrevokably decide who is responsible for checking that (where check should be). Repeating exactly same check might be considered infringement of DRY rule.

Solution 2:[2]

As you said the function that calls your my_func can change over time and start passing different values.

What you could do additionally in your code is to add Literal typing for your parameter

from typing import Literal

def my_func(my_var: Literal['val1', 'val2']) -> str:
    if my_var == 'val1':
        return '1'
    elif my_var == 'val2':
        return '2'
    else:
        raise ValueError('Unsupported value')

That way developers will have highlighted code if they will try to call your function with different parameter:

enter image description here

Solution 3:[3]

In your first code, you expect the value of "my_var" to be either "val1" or "val2". However, if the value provided is neither of the above, it raises an error. It is a good approach when expecting input from users. Rule number one, Never trust user input.

On the second function, you're only interested in the provided value "val1", otherwise, anything else is treated as "val2".

There are several instances that require either of the above functions. Example 1: You have a program where a user should choose a menu either cheese or chocolate. Here you have to apply function one since any other menu provided by the user will not be existing. The user will be limited to only those two options.

Example 2: You have a program that asks a user whether to proceed or not. Here the options are, either reply with one to continue or reply with anything else to decline. That is where function2 comes into application.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daweo
Solution 2 puchal
Solution 3 Albert Alberto