0

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?

3
  • 1
    Please describe what you'd like to do. Without context, checking whether the parameters have the default value with a regular conditional seems to be the best option. Commented Jun 5, 2020 at 6:57
  • In the case that you have provided, all of the parameters of the sdf function are given defaults and set to 0 when called. When you call with speed=10 and distance=2, then it follows that time will default to 0. But I can't satisfactorily answer the question with this since what you are asking is slightly unclear. Commented Jun 5, 2020 at 6:59
  • 1
    @jaaq basically all I would want this function to do is to calculate the parameter that has been provided. If the function receives speed and distance, calculate time and return it, if time and speed is provided, then calculate distance and return that. Commented Jun 5, 2020 at 7:09

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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

6 Comments

Note sure why this was downvoted - even the original did what was required (albeit a bit clunky).
Your answer goes against Python Zen: Checking for more than one None type is redundant because arithmetic with None causes an error to be thrown anyway. Counting for 0 None is redundant because the program will land there after all 3 conditionals returned False.
And your tuple creation has a typo, which I'd have edited if stackoverflow allowed edits as small as 2 characters. distance.speed should be distance,speed
jaaq - I expllicity wanted to control the string in the exception, hence count None and customising the exception rather than just throwing a uninformative TypeError due to a None in a calculation. I could have wrapped the calculations in a try/except, but I chose to explicitly check - I don't see why you think the 'Zen' of python is violated.
@jaaq - thanks for the heads up on the period (rather than comma) in the tuple. Thank you.
|
-1

You should use multiple functions and call the one needed.

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

4 Comments

You don't answer the question. The question was how to neatly know which of your functions to call if you you only know you'll be given 2 of the 3 parameters.
Yeah but when you call your sdf function, at that point you know which parameters you have. So at that time you can choose a different function based on what you need. Its bad practice to have a function that does multiple things.
Not if the output is consistent. You'll have to detect which parameters are present at one point in the program anyway. Better keep it consice and logically grouped than needlessly separated, imho
No, you dont have to detect which parameters are which. Because you know, if you don't know then you wouldn't know which parameters you were giving to your 'sdf' function and then your program would never work. It would be based on chance? And the functions in my answer are logically grouped and consice. However there is nothing logical about a function called 'sdf' and neither is it concise. The function name 'sdf' says nothing me when I call it. I don't know what it returns, all I know is I can give it three optional parameters? I wouldn't approve

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.