π°How Does Control Flow?
Control flows downwards... mostly.
Direct Control Flow
In the simplest of functions, control simply flows downward.
The reason this works is because the control goes up to down ββ 3 is bound to a, and then looked up in line 2. This is quite like English, so we do it intuitively.
Breaking Control Flow With If
The first way you learn how to break control is through if. If is known as the "conditional", because one of many statements is conditionally executed.
Try it out yourself in PythonTutor.
As you can see, the control arrow jumps from line 1 to line 3, skipping line 2 entirely. You could add anything to that line, and it won't error ββ because it will never execute.
Breaking Control Flow With While
Another way we could change the flow of control is to make it go over the same block of code over and over again.
The fundamental idea behind the loop is to do the same thing over and over again with small changes each time.
There are four parts to the loop ββ the initial assignment (n = 1), the iterative condition (while n < 4), the execution (printing Hello) and the updation (n = n + 1). When we combine all four of these, we get a block of code that operates iteratively.
Breaking Flow Of Control With Functions
Another, more complicated way, the control flow is broken is through functions. Take this simple example.
Try it out yourself in Python Tutor
So the function signature (that's the def
line) is read, but not the function itself. The error inside the function doesn't execute, nor is the print statement. While the function's name and number of arguments are read and saved, the body of the function is not.
Now let's think about what happens when you call the function.
First, we bind a function with one argument to f. Then, we bind a to 3. Then, we call f with a (which is 3).
This call takes you out of your "main" control flow, and creates a separate flow. You've previously thought about this in terms of a new frame.
In this frame, everything inside of the frame is accessible, and everything in all its parent frames is also accessible. Moreover, anything that gets passed into this frame is a new copy ββ the x inside of the function is not the same as the a that is passed in (This idea will grow in importance as the things we pass in get more and more complicated).
As seen, the value a is accessible despite not being in the function's flow, because it is in the parent flow. Of course, x itself is accessible. Changing x does not change a, because x is an independent copy of a.
The return value ends the function's frame and leads you back into the main flow ("global frame"). Even functions that don't explicitly have a return value have an implicit return None
statement.
When the function returns to its own frame, it brings a value with it, and normal control flow resumes.
Frames Are Independent Of Each Other
Consider the following example:
What do you think will be printed? Take a moment to try it out in PythonTutor.
You'll notice that Print 2 will return 3! So what happened to the a=4 that we defined. This is the idea of framing. The universe that f(x) operates in is different (but not completely divorced) from the universe of the main program (the global universe, if I may). The a that is defined in the function is completely different from the a that is defined before the function call. That's right ββ there are two different a s existing!
This is what I mean by "the independence of frames". That is to say, a different frame has its own defined variables that may have the same name as a parent frame.
You may feel like this idea is starting to get familiar ββ and it rightly shouldββ it's the idea behind environment diagrams! I think understanding this concept makes environment diagrams a lot more simple. Check out the quick note on those to understand how to use these concepts!
Last updated