Conditional Multiple-Return Functions
00:00 Another place programmers use pass by reference is in functions that can return two different types of things based on some condition determined in the function.
00:10 How would you go about programming a similar type of function in Python? Well, consider what type of function we might be talking about. One function like this is one that attempts to perform a task but could fail at that attempt.
00:25 It returns an actual result if successful, but what should it return if not successful? One such example would be a function that converts a string to a number, like on a web form text input box where a user has to type in a numeric value.
00:42 The string that they type has to be converted into a number for whatever calculation it’s to be used in. But what if they don’t type a number? What should the convert function do in that case?
00:54 Now, I know you might be thinking about using exceptions, and that’s a great suggestion. However, exception handling is not something every programmer is familiar with, unfortunately.
01:04 Plus, you’ll see many functions that are written in a manner similar to the example I’m showing you. Marius’s tutorial shows a function of this type in C#.
01:15 It’s a built-in function of the language and even uses examples from Microsoft’s C# documentation website. C++ doesn’t have one that behaves quite like C#’s, so I’ve invented one. I won’t go over the code in this lesson, but you will see it and it will be available on the set of source code files for this course if you want to examine it more closely.
01:39
It’s actually very similar to the Python version you’ll see later in this lesson. This function, tryParse()
, attempts to convert a provided string into a numeric value—in this case, an integer. It’s coded to take into account the possibility that the string doesn’t represent a number. It takes two arguments.
01:59 The first is the actual string to be converted. The second is an argument variable being passed by reference, which, when the function ends, contains the numeric value of the string provided.
02:12
The function returns True
if the conversion was successful, False
if not. If the conversion was unsuccessful, it’s understood to ignore the reference argument.
02:24 It won’t contain anything meaningful.
02:29
Here’s a C++ version of the program Microsoft has on its website to test C#’s tryParse()
function. It creates a collection of strings to convert, or at least attempt to convert, then processes the collection one at a time, calling the tryParse()
function on each string.
02:52
So, there’s a brief look at my tryParse()
function,
02:58 but here we want to focus on its use.
03:02
Since the function returns True
or False
based on if the conversion was successful or not, before it uses the numeric value—in this case, just to display it—it must test to see if the function returned True
first.
03:17
So you can see this if
statement testing the return value of this function. If it’s True
, we display the number. If it returned False
, we do something different.
03:31 In this case, we display an error message. In another program, we might allow the user to try again or take some other type of corrective action. Let’s look at this at work.
03:45 I’ll compile it and then run it.
03:59 Here, you can see a couple of strings that failed to be converted, but my function was able to convert most of them to an integer. You might also see some conversions you’re not happy with.
04:10
I’m not necessarily happy with them either, but this is the conversion the underlying C++ function performed. The point is, you still see output from both branches of the if
statement, meaning this function is performing mostly the way it should.
04:28 To use this type of function, your code must check first to see if the conversion was successful. If so, the variable you used in the second parameter has the converted number.
04:39 If your test indicates that the conversion was unsuccessful, then your argument variable for the numeric results should be ignored and, perhaps, some corrective action taken.
04:50
Here again is the copy of my output. And yes, my tryParse()
function has a different definition of success than the C# version used in the tutorial does.
05:02
Since Python doesn’t have pass by reference, how would we write a function that behaves similarly? Well, the short answer is, since Python functions can return multiple values, just return both the Boolean success result and the converted number if successful. Here, we call Python’s int()
function on the string.
05:25
This function throws an exception if the string can’t be converted to an integer. If the conversion was successful, it returns True
and the converted numeric value.
05:36
If the call to int()
failed and an exception was thrown, the function catches it and returns False
for the Boolean part of the return
statement and returns None
for the second part.
05:49
A call to this function should expect a tuple with two values in either case—the Boolean success result and the numeric value of True
or None
if False
. To use it in its current state is a little awkward, but it works. To test if the conversion was successful, you call the function on the string to parse and then check the first position, index 0
, of the returned tuple. If that returns True
, you know the second position, index 1
, contains the converted value.
06:22
If it returned False
, you know the second position contains None
and your code shouldn’t use it.
06:32
So, here is the Python version of the tryParse()
function, same thing you saw on the slide, and here’s where we try it out. Again, calling the function and testing the element at index 0
of the tuple to see if the conversion worked or not.
06:49
If it worked, get the element at index 1
from the returned tuple for the actual value to use. If it didn’t display, some error or take some other corrective action.
07:02 And I can demonstrate this as well.
07:13 So again, this version has a different definition of what can and can’t be converted to an integer, but you still see action taken in each case.
07:25 But perhaps you noticed something off about this version. It’s actually calling our conversion function twice: once to determine the success, the second time—if needed—to get the actual number.
07:38 You could unpack the tuple first, but that changes the logic a little bit.
07:44 So in this version, you call the function before the test, saving each element of the tuple to a separate variable. This is why it’s so important to return a tuple in both cases. Before calling the function, there’s no way to tell if the conversion will be successful or not.
08:01 That’s what the function does. But you don’t want to have a function like this return a tuple sometimes and other times not. It should always return a tuple, so in this call you can always unpack it into two separate variables. After that, the logic of this version is the same. If the conversion was successful, we use the number it converted to.
08:25 If the conversion was unsuccessful, we display some type of error message or take other corrective action.
08:33 I’m about to scroll off the bottom of the screen here, so let me reset this. Let’s look at the first program’s output for comparison.
08:45 And now the second version.
08:50
See? Same output. Just an additional step before the if
/else
branch to save the two values returned from the function. In the next lesson, I’ll show you a third version of this, which takes advantage of a feature introduced in Python 3.8.
Become a Member to join the conversation.