tomfry
tomfry

Reputation: 33

Pythonic way to detect which optional parameters are present

Still fairly new to python.

I was wondering what would be a good way of detecting what output response a python program were to choose.

As an example, if you were to make a speed/distance/time calculator, if only 2 input were ever given, how would you detect which was the missing input and therefore the output? I can think of some fairly crude ways but I was wondering if there was anything else if more complex tasks were to come into play.

I guess something like:

def sdf(speed=0, distance=0, time=0):
   # detect which parameter has no input / equals 0
   # calculate result
   # return result

sdf(speed=10, distance=2)

Any ideas?

Upvotes: 0

Views: 106

Answers (3)

Tony Suffolk 66
Tony Suffolk 66

Reputation: 9724

This is what I would do :

def sdf(distance=None, speed=None, time=None):
       """Calculate the missing speed, distance time value

          returns a 3-tuple (speed, distance, time)

          raises ValueError if more than one or no unknowns are given"""

       if (distance, speed,time).count(None) > 1:
           raise ValueError('Error - more than one unknown provided')


       if (distance, speed,time).count(None) == 0:
            raise ValueError('Not sure what to calculate - all paramaters provided')

       if speed is None:
          return distance/time, distance, time

       if time is None:
            return speed, distance, distance/speed

       if distance is None:
            return speed, speed*time, time

Upvotes: 1

jaaq
jaaq

Reputation: 1256

Python allows you to change types of variables on the fly. Since you are working with integers and 0 could be a useful value in your calculations, your default 'not present' value should be None:

def sdf(speed=None, time=None, distance=None):
    if speed is None:
         return calculate_speed(time, distance), time, distance
    if time is None:
         return speed, calculate_time(speed, distance), distance
    if distance is None:
         return speed, time, calculate_distance(speed, time)
    # All paramters have been set! Maybe check if all three are correct
    return speed, time, distance

speed, time, distance = sdf(speed=1, distance=2)

This way you don't have to find out what happened afterwards. This function will give you all three values, given you gave it at least 2 out of the 3.

If your program flow allows for multiple values be None, your functions calculate_XY should throw an exception if they detect it. So in this case:

def calculate_distance(speed, time)
    return speed * time

It will throw an unsupported operand exception(TypeError), so no need to clutter your code with useless asserts.

If you really don't know how many parameters will be set, do something like this:

try:
    retval = sdf(None, None, x)
except TypeError as e:
    print(e)
    handle_exception(e)

Also just a heads up: the is operator in Python checks if the objects are the same object, not their value. Since objects that are assigned to None are just a 'pointer to the global None object'(simplification), checking whether a value 'contains' None with is is preferred. However be aware of this:

a = b = list()
a is b
True
# a and b are 'pointers' to the same list object
a = list()
b = list()
a is b
False
a == b
True
# a and b contain 2 different list objects, but their contents are identical

Just be aware that to compare values use == and to check if they are the same object, use is.

HTH

Upvotes: 1

user8689373
user8689373

Reputation: 125

You should use multiple functions and call the one needed.

def CalculateTravelTime(distance, speed)
def CalculateTravelSpeed(distance, time)
def CalculateTravelDistance(speed, time)

Upvotes: -1

Related Questions