Rock Solid Python with Python Typing Transcripts
Chapter: Typing Guidance, Patterns, and Advice
Lecture: Point of No Return
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
Remember at the beginning of this chapter, when I talked about optional or non-optional, I said it returns a user and the only way to get out
0:08
without returning users to throw an exception. What if you never return from a function normally at all? What do you put there? Do you put none?
0:19
I don't know, you might think, Michael, that sure is weird. Well, what if you have like some kind of interactive user interface and it's while true,
0:28
ask a bunch of questions and then maybe you break out and throw a no more input or type of exception, something like that, that'd be possible.
0:37
If you use system.exit, that's like this, system.exit will signal the exit code for your program,
0:44
but it also raises an exception and immediately ends it. What if all the paths in a function use system.exit?
0:50
There's no return value, not even none in fact. So how do you express that? Well, surprisingly I think, it's surprising to me,
0:58
it actually exists explicitly in the Python type system. So here's a really, really simplistic assembly of some sort of web application.
1:10
Now, one thing that you can find often in a web app is you'll find that there might be different status codes
1:18
you want to encounter for certain things, right? So if I'm just gonna render some HTML, maybe that's a 200 response code, right?
1:27
That's the standard successful, everything worked. But there are other times to say, you know, this page was found and it's fine,
1:34
but you're not logged in yet. So I need you to go log in over there and come back. So you might throw some kind of authorization needed status code,
1:45
or it might be a redirect, like, yes, you came here, but actually there's a different URL where that lives,
1:51
and that's either permanent or temporary, right? So there might be an HTTP found, like a 301 or 302 type of thing.
1:59
So we're gonna simulate that real simple story here. So here's our fake web framework, and it says, do you want to redirect or see the page?
2:10
So it says redirect version one, because we're gonna run version two in just a second. It says we are redirecting, notice this,
2:19
we are redirecting the user, dot, dot, dot. You will see the page content and you are amazed, okay. Down here it says framework redirects exception
2:29
or some kind of bad request. So if you pass in some kind of bad information, right? Like if this is an API, you posted missing data,
2:38
the thing to say would be 400 bad requests. All right, now let's look down here. We can redirect to the URL and it can come in
2:47
and have a URL and say it's permanent. We do a permanently moved. What is that a 301 I think? And then a 302 is it's just over here,
2:56
but not necessarily forever. Just this one time, go look there. Like you've logged in, now go over to your homepage. All right, so if it's permanent,
3:06
we do one type of framework exception. If it's not permanent, we do another, or if it's bad data, we do yet a third.
3:15
But notice there's no normal return path here. All right, well, let's just run it and see what happens. So do you wanna see the redirect page?
3:23
Yes, I wanna see it. Framework redirect exception over to here. Awesome, let's run it again. No, I don't wanna see it.
3:32
You see the page content and are amazed. So anytime that we call redirect to, whether it's permanent or temporary, if I put in here true,
3:43
you get a framework redirect exception, okay? And if I put in none, you get the bad request, right?
3:55
But you never ever will see we are redirecting the user, right? Because anytime we call this function,
4:03
no matter what we pass, there's gonna be an exception. But look, PyCharm says on line eight, everything's fine.
4:10
The very next thing to happen, dear programmer, when you write this code is first it's gonna run this, and then we're gonna go here. But do you?
4:20
No, you never ever do. And while it's technically true that nothing is returned from here, more accurately is there will never be a case
4:30
where you go through this function and there's ever a return value whatsoever, right? At all. Exception, exception, exception.
4:38
So there's a V1, that means there should be a V2. And let's go up here and use V2. Nothing's changed yet besides the name. What can we put here?
4:51
We could put no return. And we can import that from typing. Typing.noreturn. Now, you might think this is like a void function.
5:04
It just means there's no known value, right? So if I had def bunch print i, right? You might say, oh, this has no return value.
5:16
That is not what this means, right? If the way to express that would be to say it has none, right, we talked about this previously, right?
5:23
So it's not this, it's definitely not that. What this no return means is there's no value at all, not even none.
5:31
Another way to think about it would be always an exception. Maybe that doesn't mean a bad thing, but always an exception. If we come up here,
5:38
for some reason it took a second, I don't know why, but notice there's now some kind of warning on line 11. What's going on here?
5:49
We call this function, it says, you will never reach this code. Why? Because no return, maybe like I said,
5:57
a better way to think of it would be always an exception. There's always an exception, and this is not in an except block or a finally or anything.
6:06
So the very next thing that happens is an exception will be thrown and you're into that block. So by virtue of going to redirect version two,
6:14
you're always here. And as we saw, this never actually did run, right? But yeah, I'll put it like this. We wanna see that warning, right?
6:27
We wanted to say, hey, you realize this is not a thing. I told you about the system.exit, right? So we could import sys.exit72. Notice, same deal.
6:39
This code is unreachable. So same idea, we don't have to exit 72 there. We want it just to run, but this, you know, maybe,
6:48
I think this is really valuable, right? So it's not a common thing to do, to have a function like this, but it's not never either.
6:57
And it's good to know about. Just, I covered this for two reasons. One, I think it's interesting to say you can express
7:02
that there will always be an exception from this function in the type system. Pretty interesting. Two, maybe more importantly,
7:10
is that if you run across no return, it's not to say that this situation, where you just don't have a return statement,
7:19
that is returning none, that's how Python works. No return should be renamed to always an exception or something like that.
7:29
All right, well, that's no return. And it's pretty interesting. It's not common in a lot of different static languages,
7:36
I think, so quite interesting to find it here in Python.