Skip to content

Programming Thinking — Transcript

Learn programming thinking with Python to harness AI effectively, covering variables, control flow, functions, recursion, and more.

Key Takeaways

  • Programming thinking is a new common sense crucial for effectively using AI.
  • Python variables are dynamic and can hold different data types during execution.
  • Mastery of variable behavior and control flow is foundational for programming.
  • Functions and recursion enable powerful, reusable, and elegant code structures.
  • Understanding value vs. reference is important for managing data and memory in Python.

Summary

  • Programming thinking remains essential even with AI advancements, as it helps maximize AI's potential.
  • The video uses Python to teach fundamental programming concepts including variables, control statements, loops, functions, and recursion.
  • Variables in Python are flexible containers that can store any data type and change over time.
  • Understanding variable assignment and behavior is critical for programming mastery.
  • The video emphasizes the difference between programming and mathematical interpretation of symbols like the equal sign.
  • Control flow concepts such as if-else and elif statements are demonstrated with practical examples.
  • Loops, including for loops and nested loops, are explained with real-world analogies and coding examples.
  • Functions and the importance of return statements are covered to illustrate modular programming.
  • The concept of value versus reference in Python variables is introduced to deepen understanding.
  • Recursion is presented as a fundamental programming technique with visualizations and examples.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
This video teaches you programming thinking. People say you don't need to write code anymore. You have AI.
00:09
Speaker A
I actually agree with that. But if somebody says you don't need programming thinking because of AI, I couldn't disagree more. To say programming thinking doesn't matter is like saying basic knowledge and common sense don't matter. We still went to school to learn
00:24
Speaker A
the fundamentals of math, science, economics because it helps us to think and ask better questions.
00:31
Speaker A
In the age of agentic engineering or vibe coding, programming thinking is a new common sense that helps you to maximize your use of AI. It's no surprise to see the value created by pure vibe coders just plateaus over time.
00:44
Speaker A
Whereas it's people with programming thinking who can harness the true potential of AI and create impactful projects.
00:53
Speaker A
Throughout this video, we use the Python language to learn about programming thinking. Starting from variable, control statement, Python list, for loop, loop with range, nested loop, function, value versus reference, dictionary, and recursion.
01:13
Speaker A
Your attention is all I need. If you invest your next 60 minutes in the video, you'll transcend from a pure vibe coder to the enlightened programming thinker.
01:26
Speaker A
The first time when we saw the equal sign, it probably dates back to grade school.
01:31
Speaker A
1 + 1 = 2. The equal sign here feels like a noun because it is statically describing a math expression. And this interpretation is buried deep within our subconscious. Yet, in programming, the equal sign means a completely different
01:44
Speaker A
thing. It's a verb. It's an action which you perform as a programmer. Using the equal sign, we store data into a variable.
01:55
Speaker A
For example, hey, the variable whose name is A, now you store the number five. And if we print A, it's going to print five. And we can use a variable A as if you were directly using a number itself. So, A + 1 is basically 5 + 1, so
02:11
Speaker A
forth, A * 3, A to the power of 2. We can also store a string to a variable.
02:18
Speaker A
The variable whose name is B now stores a string Bob. If we print B, it prints Bob. So, hello plus B is hello Bob. And likewise, my name is plus B, B plus B plus B.
02:35
Speaker A
Question. So, the variable thingy you said here, what kind of data type? Is it a number or is it a string?
02:42
Speaker A
Well, neither. The best way to think about the nature of a variable is that it is something that can store any data type, but itself is not intrinsically a data type. So, I know sometimes a variable really looks like a string, but
02:55
Speaker A
it's not because it does not have the quotes. For example, this is a variable and the name of this variable is season.
03:04
Speaker A
But this season here is a string. After you store data to a variable, which is an action we call an assignment statement, you can use a variable later as if you were directly using the data stored within.
03:18
Speaker A
Just knowing this fact, a variable is already a powerful tool. Potato was using Python to calculate the surface area and volume of a sphere. But now, suppose the radius of a sphere is no longer eight, but seven. He needs to
03:33
Speaker A
manually update all occurrences of eight into the number seven and execute this code again.
03:40
Speaker A
That's really not so efficient, right? The more clever move here is to use a variable. So, we first create a variable on top. The variable's name is R. It stores the number seven. And in our formula, rather than multiplying with a
03:52
Speaker A
specific radius, we'll multiply that with variable R, which we know now it is seven.
03:58
Speaker A
And execute again. Great, this works. From now, Potato can just easily modify the variable on top and you'll just compute the answers for that particular radius R.
04:10
Speaker A
At this point, some of you are like, "Come on, Potato. Don't be lazy. You are only manually changing the number three times. You don't need variables in your life." But our Potato could be more ambitious. He's also interested in using
04:22
Speaker A
Python to compute the surface area and volume of all the Platonic solids in this world of the same edge length. They are tetrahedron, hexahedron, octahedron, dodecahedron, icosahedron.
04:37
Speaker A
All the different types of hedron have different formulas for surface area and volume. But with the use of variable, one modification here, every line of computation below changes accordingly.
04:48
Speaker A
However, if you do want to replace all occurrences of edge length manually, it's very tiring. You get my point.
04:56
Speaker A
Let me interject with a few words about terminology. With such an assignment statement, variable A stores the number five. Another 100% equivalent statement is to say the value of A is five. I just want to let you know that the two
05:10
Speaker A
descriptions here mean the exact same thing. I would also use them interchangeably. Cool. Variables can store data. Variable has value. Why don't we just call them data container or value with a name?
05:26
Speaker A
Because a variable can store different data throughout the execution of the program. After your initial assignment statement, you can change it again and again. It can store the data of whatever you want and change whenever you want.
05:40
Speaker A
As a matter of fact, understanding how a variable changes is a critical part of programming. Hence, we need to be solid on this topic.
05:50
Speaker A
So, I'm going to ask you to do the following six quizzes. I know your reaction. Wait a second. I'm here to learn about Python variables.
05:58
Speaker A
Why are you already testing me? Although this feels a little unfair at the moment, I actually think it's a very good idea to have you use your own intuition to speculate how variables behave in Python and see where your
06:12
Speaker A
expectation misaligns with outcome. This is actually a much better way of learning and retaining information.
06:18
Speaker A
Somewhere along the middle, you might feel things start to get pretty boring, but the mastery of variables is very important. So, please stay with me through the end.
06:28
Speaker A
I'll remind you one important fact. Python program executes from top to bottom line by line.
06:36
Speaker A
Let's begin with a warm-up question first. You can pause the video and contemplate on what would this Python program print out at the end.
06:45
Speaker A
Okay. Hopefully, you have got your answer. As the program executes from the top to the bottom, the variables A, B, C, D each store their respective data.
06:57
Speaker A
On line number five, we have a string concatenation, which begins with variable A. We know that A is a string Bob adding with has earned the string of B * C * D, which is 5 * 8 * 20, 800, and
07:14
Speaker A
joined again with this week. So, the final output is Bob has earned $800 this week.
07:24
Speaker A
Quiz number one. You can go ahead to pause and ponder on this Python program.
07:30
Speaker A
The answer here is pretty straightforward. The variable is initially assigned with a string that says water and then reassigned to the result of 2 + 1, which is 3, reassigned again to the string fish, and then reassigned to the
07:44
Speaker A
number 500. But, what's the lesson here? It is that a Python variable can change between data types. The variable called thing is initially storing a string, but later it stores a number. Although this may seem somewhat trivial at the moment,
07:59
Speaker A
yet in many other programming languages like C or Java, once a variable is initially created to store a number, it can never be used to store a string later on. Therefore, Python variable is very flexible.
08:13
Speaker A
Number two. The variable A stores seven, but in the second line we create a variable B and assign variable A to it. This is the first time that a variable appears on the right-hand side of the equal sign.
08:26
Speaker A
So, what exactly happens here? What does B store? The answer is B is going to store whatever A stores.
08:34
Speaker A
A very common misunderstanding is that people tend to have this mental image, in which case we believe variable B is storing the symbol of A, rather than the value of A. That's incorrect.
08:45
Speaker A
When any variable is on the right-hand side of the equal sign, we just treat it as its value. Variable B stores the value of A.
08:58
Speaker A
In line number four, variable B is assigned as A plus 100. Since A is on the right side of the equal sign, we treat variable A as if we
09:11
Speaker A
reassigned as seven plus 100, 107. In line six, C is assigned with B. So, C is going to store the value of B.
09:22
Speaker A
In line number seven, D is assigned with C. So, D also store 107. So, the lesson here is all about assignment of one variable by another variable.
09:36
Speaker A
Number three. Line one, variable n stores number 10. Line two, the variable n appears on both side of the expression, n equal to n plus one. To be honest, this is something strange to even look at. Then, what's going on here?
09:53
Speaker A
Remember our principle that whenever a variable appears on the right-hand side of the equal sign, we treat it as if we're directly treating its value. At this point, n is 10. So, line number two is basically saying n equal to 10 plus
10:07
Speaker A
one. Line four, the variable n once again appears on both sides of the expression.
10:13
Speaker A
But, we know we just need to treat it as its value. At this moment, n is 11. So, this line is saying n equal to 11 plus one.
10:22
Speaker A
In line number six, n equal to n times two, which is saying n equals to 12 times two. So, n is 24 now.
10:29
Speaker A
Whenever I see an assignment statement looking like this, my brain automatically translate this to plus one to whatever its current value is.
10:37
Speaker A
And you might also see another way which we can write this, and that is n plus equal one. And those two statement you see here, they are the exact same thing.
10:45
Speaker A
It's just a matter of personal preference to choose either one of them to use. So, the lesson of quiz three is that a variable can update itself based on its current value.
10:57
Speaker A
Number four. The goal here is to once again test your understanding of variable assignment. A common misunderstanding would sound like this.
11:06
Speaker A
In line number two, variable k is storing the variable f. Therefore, if I change k to zero, that means f is also changed to zero.
11:15
Speaker A
But, that is incorrect. I know that you know in line number two, k equal to f is saying k stores a value of f, which is 3,000. In line number three, we change the value of k to zero.
11:29
Speaker A
But, that really had no business to do with the original variable f. So, later again, if we print F, it's still going to be 3,000.
11:40
Speaker A
Number five. So, what is the problem with this code here? Line number one and two executes normally.
11:49
Speaker A
In line number three, we set area equals to pi times radius squared. What is the value of variable pi?
11:57
Speaker A
Oh, it's 3.14. It said that on the next line. But, remember Python program executes from top to the bottom line by line. So, at precisely the timing of line three's execution, our computer has no idea the value of pi.
12:12
Speaker A
So, there is actually going to be a error. The lesson here, always define a variable before using it.
12:20
Speaker A
Number six. The last one we have here is a classic, swapping two variables value. But, did this code actually swap though? Nope.
12:31
Speaker A
The end goal here, after swapping, we should see A is 99 and B is one. In line four, A is assigned with value of B, which is 99. So, the value of A is 99 now. In the following line, B is
12:44
Speaker A
assigned with value of A, which is also 99. So, in the end, the value of the two variables did not swap. They just both became the value of B.
12:54
Speaker A
What code can we add so that in the end, their values actually swap? Perhaps you remember, after line number four, when we reassign A with the value of B, the original data which A hold, the number of one, is completely lost in the
13:10
Speaker A
environment of this program. Which means, to fix this problem, we actually need to create an additional variable here, a variable called original A to store A's original value before A changes.
13:26
Speaker A
And later, rather than assigning B with A, we assign B with a value of original A.
13:37
Speaker A
And indeed, they're swapped. The lesson here, when we want to swap two variables in this manner, we need to be cautious and we need to create an additional variable for help.
13:49
Speaker A
Although I presented them as six small quizzes, they in fact were six mini lessons to go over the fundamental of Python variable and assignment statement while having you to use your own intuition to speculate its behavior.
14:03
Speaker A
Did I spend too much time on the details? Absolutely not. Variable is such an important concept. Many years down the road, after you have written 1,000 lines of code, you will have an unceremonious realization that wait, is programming just the art of
14:18
Speaker A
creating and updating variables? And alas, let's finish with two remarks about variable naming. When coding, we really have freedom in naming the variable we create. Yet, the number one rule to follow is that variable names should be meaningful.
14:35
Speaker A
Remember our warm-up question here? It would make much more sense if I had to use a more explicit variable naming.
14:42
Speaker A
See how the one down here feels like this program is telling you exactly what it is doing and it flows like an article with high readability.
14:52
Speaker A
However, there is a few restriction on variable naming. One is that we cannot have any empty space within the variable's name.
15:00
Speaker A
To fix that, we just replace the empty space with an underscore symbol. Another one is the first character of a variable cannot be an integer, but we could put integer anywhere afterwards.
15:15
Speaker A
At the moment, everything doesn't need to be perfect. We're all beginners here. If we make a mistake, the clever Python interpreter is going to tell us where the mistake happens.
15:24
Speaker A
We just need to go and fix it. Today, we are going to learn about if, else, and Boolean values. With their help, our program gains ability to make decisions, obtaining intelligence in some way. As human, we really make
15:42
Speaker A
decision in a very subjective way, and often times, we couldn't even precisely explain our decision. We make decision based on our mood, how tired we feel, how hungry we feel, our friend's opinion on certain matter.
15:56
Speaker A
Unlike humans, computer programs make decision in the most objective way. It evaluates the current condition. Is it true?
16:04
Speaker A
Or is it false? And nothing else. We call those two the Boolean values. You might wonder, Boolean, what a weird name. So, they're actually named after a famous logician, George Boole, who believes true and false are the only two
16:21
Speaker A
values that's sufficient to describe all the logic in this world. The Boolean value is a new data type, which can be stored by a variable.
16:31
Speaker A
If I print A, it prints true. If I print B, it prints false. Notice, true, false, they're both capitalize.
16:42
Speaker A
Combined with if else, the Boolean allows our program to make decision. I think a demo is the best way to explain this.
16:50
Speaker A
The behavior here is pretty straightforward. Python still executes from top to bottom. In line number four, the if statement is checking whether happy mood is true. And now, it is.
17:02
Speaker A
When the if condition is true, our program would execute the indented code block under the if statement, and will deactivate or completely ignore the indented code block under else.
17:30
Speaker A
>> On the other hand, suppose happy mood is false. The if statement is facing a false condition, and therefore, it would deactivate the following indented code block and go ahead to execute the else part.
17:49
Speaker A
In short, using if else, our program can take different actions based on different conditions.
17:55
Speaker A
In the demo we just saw, there were a piece of syntax we never seen.
18:00
Speaker A
Whenever we use if statement to check for a condition, this line must terminate with a colon, and the following line must be indented.
18:08
Speaker A
Together, they're pretty much saying, "This indented code block only belongs to the statement here." The indentation is a must, and there are two ways you can do it. You can either indent with one tap or you can indent with four spaces.
18:32
Speaker A
Tap versus space, just who cares? Surprisingly, many, many people. There have been a long bloody war among the programming community fighting over which method is superior to indent your code.
18:45
Speaker A
Linus Torvalds and Chris Latner are perhaps two of humanity's most important software engineer. One uses tap, the other uses spaces. Personally, I'm really in no position to imply which one is better, so you pick your side from here.
19:00
Speaker A
The values true, false, are two intrinsic Boolean values, but we can also have expressions that is equivalent to true or equivalent to false.
19:14
Speaker A
For example, the value of K is 1. K + 1 less than 5. This expression is obviously correct.
19:23
Speaker A
If I print this, it actually prints true. If I change expression to K + 1 greater than 5, then it prints false.
19:32
Speaker A
Those two symbols are what we call the comparison operator because they literally compare the left and right-hand side, and the result is comparison is always a Boolean value.
19:44
Speaker A
There are a few more of them. We use this one to check for less than or equal to.
19:50
Speaker A
This one for greater than or equal to. The double equal sign to check for equality.
19:56
Speaker A
The exclamation equal to check for inequality. 1 + 1 is equal to 2. This expression is true.
20:04
Speaker A
1 + 1 is equal to 3. This expression is false. The string of three is equal to the number three.
20:12
Speaker A
False. And therefore, it is true to say they are not equal. The value of A is a string that says protein.
20:22
Speaker A
If A is equal to the string fat, then we print they're equal. Else, we print not equal.
20:30
Speaker A
You might wonder, it's pretty weird to write two equal sign next to each other.
20:34
Speaker A
Why can't we just use the one equal sign to check for equality? Remember, we have already reserved the single equal sign exclusively for variable assignment. Therefore, we must use something different for actually checking equality.
20:53
Speaker A
In the video game The Legend of Zelda, the currency is called rupee. Suppose our main character has absolutely no money now. So, we set the variable money to zero.
21:08
Speaker A
But, he finds a chest box. If the item in the box is actually a green rupee, which has a value of one in this currency system, our character has money now, and we increase his money by one.
21:22
Speaker A
But, oftentimes the item is something else, such as food, weapon minerals. In those cases, the main character need to sell the item in exchange for rupee.
21:33
Speaker A
Perfect. This code uses if else to express the logic we have. If I change the item to sword, then our character has zero money.
21:44
Speaker A
Mhm, there is one issue. In this game, there are also rupees of other colors, a red rupee worth 20, or if you get super lucky, there is the gold rupee, which worth 300.
21:58
Speaker A
So, suppose you are the game developer, how do you change this program to include more conditions?
22:04
Speaker A
One easy way is to use the elif statement, which stands for else if. You can think of elif as an additional checking of condition in between if and else.
22:19
Speaker A
In our case, if the item is not a green rupee, rather than directly skipping to the else part, we can use the elif to check if the item is a red rupee.
22:29
Speaker A
And after that, another elif to check if the item is a gold rupee. In summary, the elif statement give us more condition to evaluate in the process of decision-making.
22:43
Speaker A
In this game, we can also eat things to restore health. But, whenever we're trying to eat things, the gaming system is first going to check if the thing is actually edible.
22:53
Speaker A
So, please take a moment to consider this code right here. As ST meat skewer is edible.
23:07
Speaker A
An ancient gear is not. So a simple if else will check for this logic.
23:14
Speaker A
But actually even if our item is edible, it doesn't mean we can consume it right now. There is one more condition to be met, which is our character cannot be full health.
23:25
Speaker A
If the character's maximum health is four, then his current health must be less than four in order to eat food.
23:33
Speaker A
So how can we encode this logic into our program? Our attempt is to add another pair of if else within the first if condition.
23:44
Speaker A
So notice this line is actually indented twice. You can think of this logic here is saying something like this.
23:51
Speaker A
If the item is edible, then it still needs to go through this entire evaluation procedure again.
23:57
Speaker A
If our food is not edible, then it just skip to the else part. Wait. Line seven, the condition here is clearly true. Our current health is 2.5 and the maximum health is four. So why is line number eight not executing?
24:14
Speaker A
Very good question. The key property of if statement inside another if statement is that whenever you want to check for an inner condition, the outer condition must be true first. If the outer condition is false, it doesn't matter
24:28
Speaker A
how true the inside is because the program will just never go in there. So if I change the food back to zesty meat skewer, then the character can eat it.
24:39
Speaker A
But if I change the current health to four, then he cannot. Whenever we have if inside another if, this is called a nested if statement.
24:50
Speaker A
Honestly, when I first learned a Python, nested structure was pretty hard for me to comprehend. The only way out is just doing some coding exercise.
25:00
Speaker A
And I'll take a moment here to compare and contrast between elif versus nested if.
25:05
Speaker A
Initially today, the only thing we know about is if else. The use of elif is much like adding a new path in between them.
25:15
Speaker A
When the condition for if is false, elif give another condition to evaluate before jumping straight to the path of else.
25:24
Speaker A
The use of nested if is much more like extending an additional path from the existing one.
25:30
Speaker A
Suppose we want to get here, the only way is for the outer condition to be true.
25:35
Speaker A
And after that, the inner condition is also true. Often times, certain action can only be taken if two conditions are true at the same time. In the game, even a simple action such as shooting an arrow requires two conditions to be true.
25:54
Speaker A
One, we need to have a bow. Two, we need to have at least one arrow.
26:00
Speaker A
This is where logical operators comes in handy. The logical operator and allows us to create a Boolean expression that is only true when both condition on each side are true.
26:12
Speaker A
If either condition is false, then the overall expression evaluates to false. This expression would evaluate to false.
26:24
Speaker A
Four is equal to four. True. Zero is greater than zero. False. True and false would evaluate to false.
26:34
Speaker A
Therefore, we can use the and operator to encode our logic for shooting arrow. If has bow is true and arrow counts is greater than zero, then we shoot arrow.
26:45
Speaker A
Else, we cannot. Changing the variable has bow to false, the program outputs cannot shoot arrow." If we're really being serious, we should also decrease the main character's arrow counts by one because he just shot it.
27:05
Speaker A
In contrast to and, there is the or logical operator. The or creates a Boolean expression that evaluates to true as long as either one condition is true.
27:24
Speaker A
One way to compare them is that and is very strict. Both conditions need to be true for the expression to be true. Or is kind of soft. As long as one condition is true, it is true overall and it doesn't care which one is true.
27:38
Speaker A
When our character explores cold area, he actually lose health points for being physically exposing low temperature.
27:46
Speaker A
But, as long as he's either wearing warm clothes or he ate spicy food. Apparently, in the game, eating spicy food give you cold resistance. He no longer takes damage from the cold weather.
27:58
Speaker A
This is a good application for the or logical operator. If has a warm cloth or ate spicy food, the character is staying warm. Else, he's taking damage from the cold weather.
28:14
Speaker A
You might hear the term short-circuiting when people describe the evaluation for chain of condition in Python.
28:21
Speaker A
It's natural to suspect how does Python's logical operator and or ever relate to a physical circuit? Although the next part of the video does not help with your understanding of Python, but is pretty cool. So, I got to show you
28:35
Speaker A
their connection. To begin with, suppose we have a Boolean value true. We can represent this as a closed gate where electrons flows through.
28:47
Speaker A
If the Boolean is false, then it will be seen as an open gate where electrons doesn't get to flow through.
28:55
Speaker A
Now, here is a cool thing. Suppose we have two Booleans, we AND them together.
29:00
Speaker A
This is essentially putting the two gates in series. The only way the electrons can flow through is for both gates to be closed. If either one gate is open, the electron gets stuck in the middle, which corresponds to the
29:14
Speaker A
expression evaluating to false. On the other hand, if we OR the two Booleans, it's like putting the two gates in parallel. As long as one gate is closed, doesn't matter which one, electrons can flow through the end. When
29:29
Speaker A
both gates are open, that's when the expression is false. When we have a long chain of AND condition together, it is essentially a chain of gates in series.
29:41
Speaker A
If one gate is open, electrons cannot flow through. When we have a long chain of OR conditions, the gates are parallel together. As long as one of them is closed, the electrons will be able to flow through.
29:58
Speaker A
The lesson today was a lot of information. I'll give a quick summary. We first learn about the Boolean values, the if else statement. At this point, our program already has ability to make simple decisions.
30:10
Speaker A
And then, there were the comparison operators, logical operators, which allows us to create Boolean expression that ultimately evaluates to true or evaluates to false.
30:20
Speaker A
With the help of elif and nested if, our program can behave properly when there are multiple conditions or there's dependency between conditions.
30:31
Speaker A
Using all of them combined, we can pretty much describe any software design logic, and George Boole will be proud of you.
30:44
Speaker A
Python list is a very powerful data type. A list is like a chest box of data. You can store any numbers of data in there and retrieve them later whenever you want.
30:54
Speaker A
But I know you behind the screen is clearly someone clever. If I just read over the documentation word by word, it's boring. So instead, let's begin by telling a story about the history of poker suits using Python list.
31:09
Speaker A
Way back in the 14th century, the suits of the playing cards in Spain were nothing but familiar. The four suits were cups, coins, clubs, swords.
31:19
Speaker A
The suits, which you and me are familiar with, hearts and diamond, were not in there.
31:25
Speaker A
Yet, it was true that clubs wasn't there. People decided to make things more interesting by introducing an additional suit, which is called shields.
31:38
Speaker A
And there were five different suits in a deck. Many decades later, the Germans decided to build their own deck by starting from scratch.
31:48
Speaker A
They added the suits hearts, bells, acorns, and leaves. And those four suits gained immense popularity in Europe, but of course, not as popular as its successor. The French suits drew inspiration from the German suits. They kept the hearts, but removed
32:06
Speaker A
the bells. They replaced acorn with clubs and replaced leaves with spades. And finally, they added in the diamonds.
32:19
Speaker A
Hearts, clubs, spades, diamonds. They survived all the way to the 21st century. All right, that was a lot of informations. Let's take a moment to dissect on what just happened. To create a Python list, we use a square bracket
32:33
Speaker A
on a keyboard. If you ever wonder what those weird-looking brackets are for. They're used by programmers.
32:39
Speaker A
Normally, we create an empty list without any data in there. We can also create a list with some initial data. We will use the comma to separate them, distinguishing data from datas.
32:52
Speaker A
Sometimes, people use the word element referring to a particular data in a list. I'll use those two terms interchangeably in this video, too.
33:00
Speaker A
Here, you definitely notice something strange. The variable my list does not store the entire list, which is what everyone expected. But, rather, it is storing an arrow which reference to the actual list. Why? Strange, indeed.
33:16
Speaker A
In later chapter called value versus reference, we'll have a much more in-depth conversation about this and understand why it's really important.
33:24
Speaker A
For now, it's good to have this mental image. Variables such as number, string, boolean, the actual data is stored.
33:32
Speaker A
But, a list variable only stores a reference to the actual list. After creating list, much of your programming interaction with Python list stems from these four primary operations.
33:44
Speaker A
Access, modify, add, remove an element from the list. Zero and foremost, when we want to access an element from a list, we must know its index. For example, suppose I want to get a first element, assign it to the variable called item. We use the
34:02
Speaker A
name of the list, square bracket, index zero. Yep, what you see is correct. To get the first element, we don't use number one, we use the number zero. We call this behavior zero indexing. This is pretty important to emphasize again. The human
34:22
Speaker A
understanding of first actually translates to index zero in Python. You cannot imagine the number of human intelligence hours that had been wasted on this bug. Somewhere inside a massive software, a programmer is trying to access the first element, but the index
34:39
Speaker A
one is used instead of zero, causing the entire program to behave incorrectly. Now, here's a question for you. Suppose I want to get a third element of a list, which index would you use?
34:55
Speaker A
Index two. So, the pattern is whenever you want to access the nth element, the index used is n minus one.
35:05
Speaker A
The action of modifying a particular element feels almost identical to modifying a variable. We can modify any variable simply by reassigning it to something else.
35:17
Speaker A
In the element case, we just reassign the list index to something else. The first element of crypto list is Bitcoin, and I want to change the first element to Litecoin.
35:27
Speaker A
I just write crypto list index zero equal the string Litecoin. A variable can update from its existing value.
35:41
Speaker A
So can an element inside a Python list. This code here updates the third element, which is index two, by multiplying 1.2 with its existing value.
35:57
Speaker A
Suppose I want to modify the element Bitcoin to Litecoin. Does this code snippet here do the job for me?
36:05
Speaker A
It looks like it does, but it doesn't. The only thing we did here was to change the variable coin.
36:12
Speaker A
The element of index zero was never changed. A pretty easy place to make mistake if we're not careful.
36:21
Speaker A
When we want to add a new element to a list, we use the append method.
36:27
Speaker A
Pretty straightforward. The string Kyoto is now added to the end. Wait, this is a new syntax we never seen. What is a dot doing in the middle?
36:38
Speaker A
So, this is called a method. In later chapter, we will formally define what a method is.
36:45
Speaker A
This syntax is pretty much just saying, after the dot symbol, we're doing some action, and whatever the action is is directly related to the item here.
36:57
Speaker A
One thing notable to mention, when we append a variable to a list, we're appending its value rather than a symbol. The variable place stores a string Kyoto. If we append place to travel list, the string of Kyoto is
37:10
Speaker A
added to the end. However, if this is your mental image, you'll be incorrect. So, yeah. If this feels like déjà vu, it's because we really emphasized this concept back in chapter two.
37:31
Speaker A
When we want to remove element, we use the pop method. By default, pop removes the last element from a list.
37:39
Speaker A
We can also give it an index, and that particular index element will be removed.
37:46
Speaker A
Sometimes we don't know the index of the element we want to remove. Suppose we have a list of vegetables. One day, I find out tomato is not vegetable. Tomato is actually fruit. We want to remove fruit from vegetable list, but we don't
38:00
Speaker A
know the exact index of tomato. Frankly, we don't really care about its index, we just want to remove it.
38:07
Speaker A
We use the remove method. We just need to specify the data we want to remove, not the index.
38:13
Speaker A
Our Python list will find it and remove it for us. Even after learning those four primary operations, you might still feel there's nothing that special about Python list.
38:25
Speaker A
So, it's time to expand our imagination to something bigger. How about a Python list that contains every word in Romeo and Juliet?
38:37
Speaker A
So, I first Google Romeo and Juliet txt and there's a good website hosted by MIT. And I just copy this entire thing and paste it on my Google Colab.
38:50
Speaker A
Now, I'm going to use the triple quotation mark in the very front and the very end to enclose this entire chunk of text.
39:00
Speaker A
This thing now is actually one valid Python string. Look at the color. It's yellow.
39:05
Speaker A
Which I can assign this to a variable called RJ text stands for Romeo and Juliet.
39:11
Speaker A
Triple quotation mark is another valid way to create a Python string. The reason we don't use single quotation mark, which is what we always do, is because there are new lines within this text and there could also be existing
39:24
Speaker A
quotation mark in there as well. Allow me to inject a quick lesson on string manipulation. Although these new methods seem somewhat overwhelming, but in fact, they're just performing very simple action. The dot lower method creates a new string after turning every
39:41
Speaker A
single character into lowercase. The dot replace method creates a new string, in our case, after replacing all occurrences of comma with an empty space.
39:55
Speaker A
The dot split method, which uses a Python string to magically create a Python list. Any empty space in the string indicates boundary between elements.
40:08
Speaker A
Coming back, we first use the lower method to create a lowercase string of Romeo and Juliet.
40:14
Speaker A
Then, we replace all all punctuation mark with empty spaces And assign this to the variable RJ_text_no_pmark.
40:21
Speaker A
Of course, there are other punctuation mark besides commas. So, we update the variable text_no_pmark based on its existing value, but further replacing out all the period marks.
40:33
Speaker A
And we repeat the same process for the rest of them. And then finally, we use the split method to create a list version of the string.
40:42
Speaker A
If I print RJ_list, what I see is a long long Python list. This list contains every single word of Romeo and Juliet, which is what we want.
40:53
Speaker A
Let's ask some basic questions. What's the first word in there? What's the second word in there?
41:02
Speaker A
What's the 500th word in there? I can use the l e n len function to check for how many elements this list have.
41:13
Speaker A
This thing is a number, so I can assign this to a variable and print it.
41:18
Speaker A
Our list has 25,000 strings in there. Besides the comparison operator, the in keyword is another tool we have to create a boolean expression by asking if a certain data is indeed within the list.
41:35
Speaker A
We can ask, is the string Romeo in RJ_list? How about the string Juliet? False.
41:43
Speaker A
Oh, it's because I misspelled Juliet. Is Shakespeare's iconic thou in there? Is the word love in there?
41:52
Speaker A
False. How come? I thought this is love story. It's because I made a mistake. Remember, everything has been turned into lowercase, so it's impossible for any capitalized string to be found within RJ_list. I need to lowercase love as
42:06
Speaker A
well. Is the string poison in there? Since the in keyword us a boolean value, so we can write a if-else logic.
42:18
Speaker A
The string robot is not in there. The string Python is also not in there.
42:24
Speaker A
See, we don't even need to read the entire thing. We can conclude that the story is not about robot nor Python.
42:34
Speaker A
If anyone ask me what's the most important concept in basic programming, I would say for loop.
42:41
Speaker A
However, for us beginners, the first time seen this idea, it seems really abstract and non-intuitive. So, let's motivate this concept with a real-world example. Potato is working as a software engineer for Google now. His job is to print out every element of a Python list
42:59
Speaker A
while saying hi. And he wrote this program. Potato's clever solution is to access the first element and assign it to the variable user and print hi user.
43:10
Speaker A
After that, the variable user changes to the second element and print hi user. And after that, user changes to the third element and prints hi user again.
43:21
Speaker A
And finally, he prints work done, going home. As you can see, Potato's overall strategy is to create just one variable, user.
43:30
Speaker A
And he keeps recycling this variable by manually changing it to the next index and then print hi user. His program executes perfectly. Good job, Potato.
43:40
Speaker A
Everything is fun and games until this list starts to get really long. One morning, Potato realized user list has 5,000 elements.
43:50
Speaker A
Does it imply he's going to write code like this? I mean, this works, but our Potato is definitely exhausted.
43:58
Speaker A
Looking at his 6-hours long effort, Potato realized that his code is extremely repetitive. He is essentially just printing hi user over and over While the variable itself changes to the next one and to the next one and to the
44:12
Speaker A
next one. He wonders, what if the variable user can be a little smarter such that it changes on its own to the next element one by one.
44:23
Speaker A
So that I only need to write hi user once. And this is the entire premise of for loop, which is to automate the repetitive simple actions finding small patterns to solve big problems. Now, potato writes for user in user list colon
44:44
Speaker A
indentation print hi user. With this type of syntax, a for loop begins. The loop variable user is just going to change on its own, hopping to the next element, changes its value to that, hopping to the next element and changes
45:03
Speaker A
again. Every time after user change the next element, the entire indented code block under the for statement will be executed.
45:13
Speaker A
The for loop is going to repeat this change execute change execute change execute alternating actions tirelessly all the way to the end. There is a sensation that the for loop is running.
45:27
Speaker A
No matter how long this Python list is, whether it's 50 elements, 50,000 elements, or 50 million elements, potato's program would run properly.
45:41
Speaker A
A few syntax to point out. Remember in the previous chapter, we learned that the in keyword can check whether data is indeed inside a list. The same in also appears when we're writing for loop. I just want to say those two in means
45:55
Speaker A
complete different things under the two different contexts. This in is more like asking a question.
46:02
Speaker A
Is it in there? This in is more like a statement saying that the loop variable user will change its value one by one to every element inside the list.
46:14
Speaker A
Once again, we see the familiar colon and indentation syntax, which we had previously seen with if else statement.
46:21
Speaker A
Only the indented code block will be executed repeatedly when the loop is running. Things outside a for loop will not be a part of the loop action.
46:31
Speaker A
And this indented code block can definitely be well more than one line. Up next, we're going to get ourselves more familiarized with for loop by tackling three coding tasks while highlighting some common mistakes and misconceptions along the way.
46:47
Speaker A
Suppose we have a list of numbers. This list can be short or very long.
46:54
Speaker A
Your goal is to find out what's the summation of the list or if we literally add all the numbers together, what would it be?
47:03
Speaker A
If you've never seen a question like this before, I promise you the answer will be non-obvious. So, for sure take a moment to pause and ponder.
47:14
Speaker A
So, the central idea is to create a variable outside before the loop starts running. We initialize the variable S to zero.
47:23
Speaker A
When the for loop is running, we keep adding values into the variable S. Currently, the loop variable number is 100. The code block to execute is S equals to S plus number, which means we update S by adding 100 to it. So, S
47:46
Speaker A
becomes zero plus 100, which is 100. After that, the variable number hops to the next one. Number changes value to five. The value of S at this point is 100. We increase it by 5. So, S becomes 105. Of course, the variable number hops
48:05
Speaker A
onto the next one again and updates S again. This process repeats. So, the variable S is getting bigger and bigger by accumulating all the index the loop has passed through.
48:19
Speaker A
By the time when the loop terminates, the variable S has already collected all the values along the way.
48:26
Speaker A
Pretty ingenious, right? The variable S is a critical data we want to update in the midst of a for loop. A very common mistake, which I definitely made often, is that we put the variable S inside a for loop rather
48:42
Speaker A
than the outside. Let's see why this is a big problem. S equal to zero. Since the variable S does not exist yet, this means we're going to create the variable S and initialize it to zero.
49:01
Speaker A
S equal to S plus 100, so S becomes 100. So far, so good. Number hops to the next element. As you can see, the line S equal to zero is within the indented code block. So, it's going to get itself
49:14
Speaker A
executed every time. S is reset to zero. But, what about the 100 we had seen before?
49:22
Speaker A
It's not accumulating anything. Even when this loop reaches to the end, the variable S does not remember anything it seen before. Obviously, this is a problem.
49:34
Speaker A
So, the lesson here is we have to be really cautious about what variable to put inside versus the outside of a for loop.
49:45
Speaker A
All right. Spent a long time on the previous one. Task two. Suppose we have a list of natural numbers.
49:51
Speaker A
How can we find the biggest number in there? The solution, once again, is that we're going to create a variable outside the for loop called the current max. The idea is to have this current max variable to store the biggest number the
50:07
Speaker A
loop has seen so far. So, it's initialized to the smallest natural number. As the loop starts running, we use a condition statement to check whether we should change current max.
50:24
Speaker A
For example, at this moment, loop variable number is 17, and current max is five. 17 is bigger than five, but this also means that the current element is bigger than every single element the loop has yet seen. So, we must change
50:38
Speaker A
the value of the current max to 17. On the contrary, if the value of number is less than current max, for example, number is 12 and current max is 17. That means there definitely exists an element somewhere before the current index it is
50:55
Speaker A
bigger than 12. So, we don't change anything and move forward. As the loop reaches through the end, the variable current max has been compared with every single index. Every time when current max faces a larger number, it changes to that. So, by the end, current
51:10
Speaker A
max certainly stores the biggest number in this list. Common question one, do I have to name the loop variable as number?
51:22
Speaker A
Nope. You have complete freedom in choosing the variable name. You can also name it current element or just cur or even c.
51:33
Speaker A
As long as you use them consistently, it's going to work. Common question two, when the loop terminates, namely outside the loop's indentation, can I do something about the variable c? Like, can I print it?
51:45
Speaker A
So, we cannot. The loop variable is kind of like a ephemeral variable that only exists when the loop is running.
51:54
Speaker A
When the loop terminates, the variable C just vanishes after having done all its work. It disappears completely from the environment of our program. Outside the for loop, we cannot do anything about this variable.
52:09
Speaker A
Suppose you and many friends are going on a road trip. You surveyed everyone for movies to watch together as a group.
52:16
Speaker A
You asked them to append their own favorite movie to the list. And since certain movies are really popular, this list has some redundancies.
52:24
Speaker A
As a group leader, you don't want to bore everyone by asking them to watch the same movie twice. Your goal is to create another list in which every element is unique. Or every movie only appears in there once.
52:40
Speaker A
The idea is similar. We create an empty list outside. As the for loop starts running, we conditionally append movies in there.
52:49
Speaker A
Since I never touch on this not logical operator, let me inject a quick lesson on this.
52:54
Speaker A
Suppose I have a Boolean true. By putting not in front of it, it negates to false.
53:00
Speaker A
By putting not in front of false, it negates to true. The thing on top is a Boolean expression that evaluates to true.
53:08
Speaker A
By putting not in front of it, it evaluates to false. As the loop begin, the variable MV stores a string Endgame.
53:26
Speaker A
By our design, unique list cannot have any redundant element. We only append new movies in there if it is currently not in unique list.
53:34
Speaker A
At the moment, unique list is empty and Endgame is not in there. We append.
53:40
Speaker A
Hopping to the next one. Spider-Verse not in unique list. True, we append. Next one.
53:48
Speaker A
Endgame is already in there, we do not append. So, if my verbal commentary of four loops start to get pretty monotonous and predictable for you, hey, yeah, you start to really internalize four loop now.
54:06
Speaker A
Looking back at our journey so far, we attempted to define a word programming. In chapter zero, we said programming is creating interesting things. In chapter two, we said programming is art of changing variables. Today, the definition is more refined. Programming
54:22
Speaker A
is art of changing variable in the midst of running four loop with conditional statement.
54:28
Speaker A
The reason why I cherry-picked those three particular examples, because on one hand, I think it really drives this thesis home. On the other hand, there's some concrete setting for us to engage with programmatic thinking. Rather than just using four loop to print out Python
54:41
Speaker A
list elements. Four loop is about finding small pattern to solve big problem using their few lines of code to work with a list of data that could be unimaginably long.
54:51
Speaker A
In many future coding situation, I promise you that you can find archetype of thinking stemming from these three examples.
54:59
Speaker A
Next chapter, we'll learn about a more generalized technique of looping, and we'll see many beautiful connections between coding and mathematics. See you there.
55:12
Speaker A
In the previous chapter, we learned that whenever there's a Python list, we can use a four loop. The four loop is a great method for automating repetitive and simple actions.
55:24
Speaker A
The loop variable keeps hopping onto the next element, changes value to that, and the indented code block executes. Those action repeats. There is a sensation that the four loop is running.
55:39
Speaker A
As programmer, we call this running a for loop over a list or simply looping over list.
55:45
Speaker A
But a more professional way to call this is iterating over a list. As vocab, iterate means to do again, do again, do again.
55:54
Speaker A
Yet, Python list is not the only thing that can be iterated over. In fact, it belongs to a larger abstract class of objects called iterable.
56:04
Speaker A
I know this entire playlist is aimed for beginners, so we're not going to the details about what exactly this word mean. So, for now, if I tell you something is an iterable, that means it can be a target of for loop. And the
56:17
Speaker A
range object is an iterable. By calling the range function with a start and end index, we get a range object.
56:26
Speaker A
But what exactly is this range object? You can basically think about it as a sequence of numbers that can be loop over.
56:35
Speaker A
When the for loop starts, the loop variable I iteratively binds to all integer from 0 to 9.
56:42
Speaker A
As you see, when we loop over the range object, it logically just feels like we're looping over a Python list, which contains the sequential integers.
56:54
Speaker A
Notice range 0 10 does not give you the number 10. It only gives you all the number from 0 to 9.
57:02
Speaker A
This is because Python's end index is always non-inclusive. If we want the number 10 in there, we have to change this to range 0 11.
57:13
Speaker A
So, what exactly can we do about this range object? A sequence of numbers doesn't seem any useful at all.
57:22
Speaker A
We can use the range to indirectly loop over another Python list. For the range object, the start index is 0 and the end index equals to the length of the list.
57:39
Speaker A
As the for loop begins, the loop variable I is integer, but it conveniently also represent the index of my list. Then, we can access the corresponding element using this index and store it into variable var and print it.
57:56
Speaker A
Since we're iterating over all the indices, we ensure that every element is visited. What you see now is another perfect valid way of looping over a list.
58:15
Speaker A
So, let's take a moment to compare and contrast between the two strategy of looping.
58:20
Speaker A
In the direct method on left, the loop variable var directly binds to the element, and we can use it immediately.
58:27
Speaker A
On the right, the indirect method, where looping over a sequence of numbers, the loop variable I only binds to an integer, and then we use the integer as the index to access the corresponding element.
58:40
Speaker A
So, this one here is a two-step process. Potato's like, "The indirect method is so inefficient. Why would anyone ever want to loop over a bunch of indices?
58:51
Speaker A
Just do it directly." Thank you, potato. That's indeed a very good question. It turns out looping over indices has the advantage in certain cases.
59:02
Speaker A
Consider this scenario. We have a list of numbers, which stores the hourly salary of six different employees, and we want to increase everyone's money by $5.
59:14
Speaker A
Potato's like, "Easy. Gotcha." He writes a Python code for salary in salary list, salary equal salary plus five.
59:26
Speaker A
As the loop begin, you already see the problem. The only thing that this code is doing is just increment the loop variable salary by five.
59:37
Speaker A
But the actual element in salary list is never changed. Therefore, this code is incorrect.
59:46
Speaker A
So, to fix that, we must use the indirect method, loop through the indices of the list.
60:02
Speaker A
As the for loop begin, the loop variable I iteratively binds to all the index of salary list, and we increase the element sitting at index I by five.
60:14
Speaker A
Here, we clearly see the data inside the Python list has been changed. So, the lesson is if we want to modify the actual element inside the list, we need to modify them through index.
60:27
Speaker A
Therefore, we must loop over the range object. Hey, isn't it bit verbose to write code like this?
60:36
Speaker A
Yep, I should use the more compact syntax of updating variable, writing plus equal five instead.
60:46
Speaker A
Another application of range object is that sometimes we want our program to make decision based on the index of the element rather than the value of the element. Still using the salary list as an example, but this time we want to
61:01
Speaker A
increase the salary of a few workers by $10 because they're just so amazing. Namely, there is another list which stores the indices of those candidates who we deem as amazing. For everyone else, we still increase their money by
61:16
Speaker A
five. Our program logic here is very straightforward. We iterated over all the indices with the help of if else, we differentially increase the salary by checking whether if the candidate is amazing.
61:37
Speaker A
Loop variable I binds to zero and the index zero is not inside amazing list.
61:43
Speaker A
So, our program jumps to the else part, increase the salary by five. I then binds to one. The index one inside amazing list, true.
61:55
Speaker A
So, we increase the element by 10. The same logic repeats all the way till the end.
62:10
Speaker A
In general, as a Python programmer, it is important to be absolutely fluent with both technique. So, depending on different coding task, we can always pick the most optimal strategy to loop over list.
62:25
Speaker A
Yet, sometimes our main focus does not have to be a list, but rather a sequence of number themselves. In particular, when we're doing computation that relates to math.
62:36
Speaker A
Have you ever seen a funny-looking thing like this? An exclamation mark next to a number.
62:42
Speaker A
It's called the factorial of that number. The factorial appears often in probability, number theory, calculus, and many other fields of mathematics, playing important role in mysteriously elegant equations.
62:57
Speaker A
Yet, its definition is very simple. The factorial of a number n is defined as the product of all the numbers from n to one.
63:06
Speaker A
For example, 5! is 5 * 4 * 3 * 2 * 1. If someone throws me a pen and paper and ask me to calculate this expression, this is what I would do.
63:18
Speaker A
Firstly, I know that multiplication is commutative, so I can rearrange the expression by reversing the numbers.
63:25
Speaker A
Then, I'll iteratively multiply the two front numbers together. 1 * 2 is 2, 2 * 3 is 6, 6 * 4 is 24, 24 * 5 is 120. So, 5! is 120.
63:42
Speaker A
But, the process certainly gave me some inspiration. Those sequential numbers just look like a ranged object.
63:49
Speaker A
The action of repeated multiplication also rings a bell with the spirit of loop. So, let's write a program that can compute the factorial of any positive integer.
64:00
Speaker A
We initialize the variable P as 1 outside the loop. When the loop is running, we iteratively multiply the variable I into P.
64:19
Speaker A
The variable P basically serves as a collector, storing the product of all the natural number it had seen as a loop marches forward.
64:36
Speaker A
You might wonder, why are we setting the outer variable P to be 1 instead of 0?
64:40
Speaker A
Isn't that what we always do before? The reason is because 0 multiplied by anything is 0.
64:48
Speaker A
Suppose I accidentally initialize P = 0. This is what's going to happen. P equals to I * P, so P equals to 0 * 1, so P is 0.
64:59
Speaker A
P equals to 2 * 0, so P is still 0. P equals to 3 * 0, so P is still 0.
65:07
Speaker A
As you see, the value of P is trapped at 0, never accumulating anything. This is a problem.
65:16
Speaker A
Normally, when the purpose of the for loop is to add bunch of numbers together, the outer variable is initialized to zero.
65:23
Speaker A
When the purpose of the loop is to multiply bunch of numbers together, the outer variable is initialized to one.
65:31
Speaker A
N is a variable, and I can initialize it to a different value, such as 52.
65:36
Speaker A
Run this again. The factorial of 52 Huh, this number is pretty big. You know, the lesson so far today has been pretty intense.
65:49
Speaker A
So, why don't we take a break together by taking a detour on this 52 factorial?
65:54
Speaker A
This number is in fact so big that people are making videos online explaining how big the number is.
66:01
Speaker A
While I was watching them, I got a sense that human beings are actually pretty bad at comprehending big numbers.
66:07
Speaker A
52 factorial is a big number. The net worth of Elon Musk is also a big number.
66:13
Speaker A
Currently, in 2022, Elon's net worth is estimated to be around 200 billion dollars. I believe a few years later, that number would increase to 800 billion dollars.
66:27
Speaker A
But, you know what's a number so much and so much bigger than that? The number of atoms on Earth.
66:33
Speaker A
Which is estimated to be 1.33 * 10 to the power of 50. All right. The next part might appear weird to you, but imagine if every tiny little single atom on Earth, each and every one of them, transforms into their
66:49
Speaker A
own pile of 800 billion dollar cash. The aggregation of total value here is really immense.
66:57
Speaker A
And that equals to Elon money times num atoms. And this is truly a big number.
67:04
Speaker A
So, which number is bigger? 52 factorial or 800 billion times the number of atoms on Earth?
67:13
Speaker A
Personally, I think the latter number must be bigger. Oops, I'm wrong. 52 factorial is bigger.
67:22
Speaker A
Well, then what fraction does this big number occupy in 52 factorial? 1.31 * 10 to the power of minus six.
67:31
Speaker A
That's a small portion. To visualize, the yellow cube represents 800 billion times the number of atom on Earth.
67:37
Speaker A
The larger green cube represents 52 factorial. Wow, this 52 factorial is so big. In what occasion does this even appear in a human's life?
67:50
Speaker A
It's all the different unique ways you can rearrange a poker deck. All right, break is over. Let's come back to Forloop.
67:58
Speaker A
Mushroom is taking a math class and she got this answer for a question. This entity may look unfamiliar to some people. It's called the sigma notation.
68:08
Speaker A
It appears pretty often in math, actually. Mushroom wants to find out the numerical value of this expression.
68:14
Speaker A
Since Potato knows Python, she goes to Potato for help. However, Potato is scared anytime when a Greek symbol appears in math. He doesn't know whatever this thing is. So, Mushroom explains.
68:28
Speaker A
The sigma notation is actually only doing something very simple. Consider all the natural numbers starting at one ending at 10.
68:38
Speaker A
We pattern match this expression to them one by one. And then, we add them together.
68:51
Speaker A
Sigma notation is just a compact way of describing summation. Potato understands now. But, wait a second. A sequence of consecutive numbers adding a bunch of numbers together both of which are just screaming out use for loop.
69:08
Speaker A
I mean, one day in the future, whenever you see a sigma notation in math, you're just going to involuntarily ask yourself it's just a for loop, right?
69:20
Speaker A
Potato picks up Python and passionately programs. And I will stop talking to let the animation speak for itself.
70:06
Speaker A
Whenever we use a for loop, we can literally put anything inside its indented code block. Within loop, we can print, we can do variable manipulation, conditional statement, we really have complete freedom as programmer.
70:21
Speaker A
But what if I put another for loop inside a for loop, which results in a nested for loop?
70:28
Speaker A
Loop inside loop. And this is when things starts to get interesting. For me, frankly, there's something unsettling looking into a nested for loop. What exactly happens? Most people have this intuition about a nested double for loop, saying, "Well, if a
70:44
Speaker A
single loop is all about one loop variable hopping over each element of its iterable, then a double for loop must be about Well, there are two different loop variable, then two different loop variable are simultaneously running over two
71:00
Speaker A
iterable. And unfortunately, this intuition about how double for loop works is just incorrect. So, what is the true behavior of a double for loop?
71:11
Speaker A
Remember that there are two loop variables, VL for the outer loop and VN for the inner loop.
71:18
Speaker A
The VN needs to complete its entire trip for VL to only advance by one step.
71:25
Speaker A
Or you can imagine this. Every time when VL takes one step forward, VN needs to complete its entire loop.
71:33
Speaker A
VL takes another step forward, VN completes another trip. So, when the outer loop terminates, the inner loop has been iterated over many, many, many times.
71:45
Speaker A
At least for me, this behavior is slightly unexpected. This is important. Let's watch this again.
72:03
Speaker A
So, if we were to look at the output generated by the print statement here, it's going to look something like A1, A2, A3, A4, A5, B1, B2, B3, B4, B5. You kind of get the point.
72:24
Speaker A
You also notice the value of the outer loop variable is persistent for the entire duration of the inner loop. This outer loop variable, which currently is D, is used to concatenate with every single inner loop element before it
72:40
Speaker A
expires and advance forward to become E. Despite its complexity, nested for loop is used inevitably in programming, such as a matrix multiplication and dynamic programming.
72:53
Speaker A
But today, let's just focus on a very simple application. Suppose I'm coding a poker game. So, the first thing I need to do is to create a deck of 52 cards, which is conveniently represented as a Python list.
73:07
Speaker A
I'll just manually add each card in there one by one. I append two of hearts, two of diamonds, clubs, and spades.
73:15
Speaker A
And after doing this 52 times diligently, I'm done with my deck of cards. But, this just doesn't feel like the most efficient way of doing things.
73:24
Speaker A
I could make the observation that a poker deck only has 13 different rank and four different suits.
73:31
Speaker A
The formation of a deck is just each rank take four different version of suit.
73:36
Speaker A
It's just combination. And this looks suspiciously like a double for loop. Therefore, I can write my Python code as I have my outer loop iterating through all ranks.
73:49
Speaker A
The inner loop iterating over each suit. And the card is simply the concatenation of a suit and rank.
73:56
Speaker A
And I append the card to my cards. And this double for loop will get my deck of 52 cards.
74:08
Speaker A
At this point, it's totally okay to feel nested loop is kind of hard. Absolutely. Especially if it's your first time seeing this.
74:16
Speaker A
Compared to a single for loop, the complexity of double for loop is in fact not double, but square.
74:24
Speaker A
Unfortunately, things can even get harder from here. Let's take a moment to compare the two different program here.
74:32
Speaker A
Can you spot out why the code on the right is much more difficult to understand?
74:37
Speaker A
Feel free to pause and ponder. All right. If we look at the left program, the inner loop always loops over from the range 0 to 5, independent of the outer loop.
74:53
Speaker A
On the contrary, the right one, the inner loop is iterating over range 0 to I.
74:59
Speaker A
But, what is I? I is the outer loop variable, which means it changes through the execution of the program.
75:08
Speaker A
The iterable of the inner loop depends on the outer loop. There is a fundamental dependency between the two loops.
75:16
Speaker A
So, what does that look like? When the outer loop just begin, the loop variable I binds to 5. According to our program, the inner loop needs to take a trip from 0 to 4.
75:30
Speaker A
As the inner loop terminates, the outer loop take one step forward. I is now 6, which means the inner loop needs to iterate from 0 to 5, which is one more than its previous run.
75:41
Speaker A
I binds to 7, the inner loop goes from 0 to 6. I binds to 8, the inner loop needs to go from 0 to 7.
75:51
Speaker A
I binds to 9, the inner loop needs to go from 0 to 8. So, you already see the pattern. As the program execute, the extent in which the inner loop needs to iterate also increase. The behavior of the inner loop, how much work it does,
76:07
Speaker A
is depend on the outer loop. Why would a programmer ever use a nested loop that has dependency?
76:16
Speaker A
Well, remember from last chapter, we learned about factorial. If we want to compute the factorial of integer n, we use a for loop from 1 to n, iteratively multiplying each number, and accumulate into p.
76:32
Speaker A
However, what happen if someone throws me list of integer, and ask me to compute each one's factorial? What should I do?
76:40
Speaker A
Let's look at this again. This block of code computes the factorial of n, and n is a variable. I can change n to 11 and see that the factorial of 11 is a big number.
76:52
Speaker A
So, why can't I change n into a loop variable iterating over number list? And it would just migrate this entire code block inside, of course, indented.
77:05
Speaker A
Notice we have a nested loop with dependency of the inner loop range from 1 to n + 1.
77:11
Speaker A
The mission of the outer loop is to iterate all integers from this given list. The mission of the inner loop is compute the factorial of that corresponding n.
77:21
Speaker A
Execute. Great. There is one detail to point out. Notice on line two, p equal to 1 is in between the outer loop and the inner loop. This means that every time when the variable n take one step forward, rather than
77:38
Speaker A
launching the inner loop immediately, the first thing it does is to reset p back to 1, then follows the entire inner loop. This reset is critically important because when the inner loop is calculating the factorial, the value p
77:52
Speaker A
gets pretty big. As the outer loop take one step forward, we need to reset p back to 1, so the residual from the previous inner loop does not linger over.
78:05
Speaker A
Loop is the most important concept in the basics of programming, which is why we spent three chapter on this topic. We start learning about loop from a visual approach. We see with our eye that the loop is really running. In part two, we
78:19
Speaker A
learn about how to loop with the range. And today, we saw the unexpected complexity of a nested for loop.
78:25
Speaker A
In terms of big picture of essence of Python, we have already added these items to our toolbox. Variable manipulation, which is a unit of compute, conditional statement, decision making, Python list, data structure, for loop, automation of logic.
78:42
Speaker A
These combined may only occupy 20% of Python's programming feature and syntax, but the core concept are definitely relevant in at least 80% of any programming thinking.
78:53
Speaker A
An interesting note aside, when Vitalik was developing the next generation blockchain, Ethereum, he was especially aware about the feature of loop. He realized that Bitcoin's foundational limitation is that it doesn't allow loop. So, he added a loop in Ethereum,
79:07
Speaker A
which enabled it to become versatile platform for developer to make interesting application. When people say function, we think about the X and Y axis. This is a linear function. This is a quadratic function.
79:25
Speaker A
Our impression about function is often a static image we see in our math textbook. However, this is actually quite misleading because the essence of function is not static. It's dynamic.
79:37
Speaker A
Function is all about the action of transforming input into output. For example, this function here computes the squared value of any number.
79:49
Speaker A
Five enters the function. Five squared is 25. And 25 is the output. And this function here is capable of interleaving two input string. A A A A, B B B B are the inputs. The function inter- leaves them
80:06
Speaker A
and outputs the longer string. What you saw just now very much resembles the essence of a Python function. There is an input. The function does something to the input and returns the output back to you.
80:20
Speaker A
This is a good mental picture to have before the lesson begins. In Python, function is a great way for organizing logic and prevents you from writing repetitive code. To motivate this, let's see an example.
80:33
Speaker A
Recall in chapter five, potato mastered the use of for loop, and now he's a senior engineer at YouTube.
80:41
Speaker A
But, what is he doing today? You can pause the video to take a look.
80:48
Speaker A
Seems like potato is writing a greeting message to members in the gold, silver, and bronze class.
80:57
Speaker A
If today is a member's birthday, he writes, "Happy birthday." Plus the person's name. Else, simply greet with, "Hey." Lastly, the message is printed with the person's class tier.
81:12
Speaker A
However, if you were to notice, these three blocks of code are identical. This is very repetitive, and this is not good code.
81:21
Speaker A
Really, in those three places, potato is seeking for the same functionality. Given person's name and his birthday as input, we want to get its corresponding message as the output. This is a great place we should use a function.
81:41
Speaker A
Finally, how do you make a function? We use the def keyword, short for define. Follow that, we give the function a name, greet, and then, within the parentheses, we specify what are the inputs to the function, which is the
81:56
Speaker A
name and birthday today. The professional terminology is that they are the parameters of the function.
82:03
Speaker A
Now, we can write code that performs action to the parameters. Notice indentation here, which is saying everything within the indentation belong to the function greet.
82:14
Speaker A
The return keyword specify the output, which is the conditional message. I want to take a moment to emphasize that the return statement here is very important. If you forget to write a return statement, you can imagine that your desired output gets stuck inside a
82:29
Speaker A
function with nothing visible from the outside. This entire thing is a function definition. We define the input, the action, the output. But when a function is defined, nothing happens yet. It's sort of just sleeping there, but ready to be summoned.
82:47
Speaker A
It is not until the line you are calling the function with actual input. Notice the def keyword is not here, and the parentheses contains real string and boolean.
82:56
Speaker A
This is when you want your function to do its magic. The greet function transform the input into the output.
83:05
Speaker A
Question. What exactly is this parameter thing? Are they like variable? They're a little unintuitive to look at.
83:12
Speaker A
Good question. They're not exactly a variable. If you think about it, when we define a function, we never know what will be the actual input. They could be anything.
83:22
Speaker A
Therefore, the parameter serves as a placeholder variable, and we write code in respect to those placeholder.
83:30
Speaker A
Only when we're calling the function, the placeholder variable manifest into the value of the real input.
83:36
Speaker A
Let's look at the execution of function in detail. Once again, when the function is defined, nothing happens.
83:45
Speaker A
At line number eight, function greet is called with tangible input name for Erin and a false for birthday today.
83:55
Speaker A
The two placeholder now manifest into Erin and false. And then the original code for the function executes.
84:03
Speaker A
And the value message is returned and bind it to the variable M. You might have noticed something. These two assignment statement was not part of the code we wrote.
84:17
Speaker A
But I intentionally put them here because this is a correct mental picture I want you to have.
84:22
Speaker A
When placeholder parameter finally takes on the value of real input, it is basically an implicit assignment statement as they are top.
84:31
Speaker A
Now, we can go back and improve potato's code. Message now becomes the return value of a function.
84:39
Speaker A
This code is much better now. Let's look at a few more examples of functions together, and you will see just how versatile function design can be.
84:48
Speaker A
You can make a function that has one parameter, or three parameters, or 10 parameters, or even zero parameter.
85:02
Speaker A
Notice when you're calling a function that has zero parameter, you still need to pass in the parentheses, but just with nothing inside.
85:09
Speaker A
You can almost sort of think the parentheses as something that activates the function. What code can I write inside a function?
85:18
Speaker A
Literally anything. You can write a for loop. This function computes a factorial. You can write conditional statement. This function converts temperature between Celsius and Fahrenheit.
85:29
Speaker A
Your function can even use other function, which is defined previously. This check password strength function uses two other function for its internal logic.
85:39
Speaker A
In terms of function design, the only limit is your imagination. Many YouTube video out there often like to motivate Python function as a way to package print statement together, rather than looking at the essence of function, which is all about input and
85:58
Speaker A
output. This type of teaching leads to a common confusion, which is what is difference between print versus return inside a function.
86:08
Speaker A
Let's look at the two function here. If I execute the function on the left, it prints hi Bobo.
86:18
Speaker A
If I execute the function on the right, it returns Hi Bobo and then I print it.
86:22
Speaker A
On both screen, I see Hi Bobo. So, there's no difference, right? Hm, not quite.
86:31
Speaker A
Notice the function on the left. It doesn't have a return statement. So, the function has no output.
86:37
Speaker A
What happens here? When a function doesn't return anything, Python secretly make the function return a none value to indicate the absence of anything.
86:50
Speaker A
So, if I bind the return value of the function to M and I print M, ah, what I get is a none here.
86:59
Speaker A
If I want to print Hi Bobo five times, I cannot. I get none five times because the variable M is a phony and the function didn't return me anything at all.
87:09
Speaker A
Whereas I could do with the function on the right because it return. Moral of the lesson here, don't fool yourself by printing inside a function and think that's a return value.
87:20
Speaker A
Before we wrap up a session today, there is one more critical concept you need to take away.
87:25
Speaker A
The return statement Python immediately terminates the execution of function. When the return statement is triggered, the function stops in a non-negotiable way.
87:35
Speaker A
My question for you, take a moment to pause and ponder. If I'm calling the boot computer function on the input false, would I see these lines of code being printed?
87:50
Speaker A
The answer is no. I would not see them because my input for has OS installed is false.
87:56
Speaker A
At line number five, the if statement evaluates not false, so true. Then it executes the return zero, which immediately terminates the function.
88:06
Speaker A
Everything afterwards is ignored. By the way, I also just learned that you could actually put emoji in Python string.
88:15
Speaker A
Question. If you have a return statement inside a for loop, can the return statement even stop the for loop before its completion?
88:23
Speaker A
Absolutely, it can. Let's take a quick detour into prime number. Quick review. A prime number is a natural number strictly greater than one that is not perfectly divisible by any number smaller than itself other than one.
88:38
Speaker A
For example, seven is a prime number because when seven is divided by any smaller number, the remainder is always non-zero.
88:49
Speaker A
Nine on the other hand is not a prime number because 9 / 3 is 3 with a remainder of zero.
88:58
Speaker A
One thing I can tell you is that prime number holds a special place in the heart of mathematician and computer scientist.
89:04
Speaker A
Prime numbers are the backbone for internet security. Without prime, your password, bank info, messages would all just be public.
89:13
Speaker A
And as programmer can easily write a function to check if a number is prime or not.
89:17
Speaker A
The is_prime function uses for loop to iteratively look at all the natural numbers smaller than n, but excluding one, and it compute the remainder. If the remainder is zero, then immediately we know that it's not a prime number.
89:31
Speaker A
Only if all iteration of the loop has a non-zero remainder, then n is a prime.
89:37
Speaker A
If what I said is a little confusing, let's see what happens when I call the function on the number 25.
89:44
Speaker A
So, firstly, n binds to 25. 25 is bigger than one, so it skips here.
89:50
Speaker A
Now, we're running a for loop from 2 to 24. We check the remainder of 25 / 2.
89:59
Speaker A
Not zero. So, we do not enter the return statement. We do the same for three.
90:05
Speaker A
We do the same for four. Now, the remainder of 25 / 5 is zero and the return statement is triggered.
90:15
Speaker A
This function immediately stop and return false. 25 is not a prime number. Notice how all the latter parts are just ignored.
90:24
Speaker A
The loop didn't even get to them. And finally, the return value false bind with the variable result.
90:33
Speaker A
Well, since I just defined the is prime function, I get to use it. Let's append all the number between 1 and 1,000 to a list.
90:42
Speaker A
Let's see who are these guys. And how many of you are here? What about between 1 and 10,000?
90:53
Speaker A
Hm, very cool. Function, input, output. I said them a million times and I bet you're tired of it. But that's the essence of function and I hope you can internalize that idea.
91:06
Speaker A
Programming and computer science ultimately is about abstraction and abstractly speaking, many things are functioning our life.
91:14
Speaker A
We know that this is a function, but an ATM is also a function. The input is your card and PIN number. The output is the money.
91:24
Speaker A
Even this is a function. The input is a character. The function miniaturize the input and a smaller character is the output.
92:00
Speaker A
You might have noticed something interesting. Every time when a function call happens, it creates a sandbox like this.
92:07
Speaker A
All variable assignments, program logic happens within. When a function returns, this sandbox vanishes. You might wonder, what is so important about this mental picture of a sandbox?
92:19
Speaker A
Well, let me show you. We have variable X equal to 1. Then we create a function.
92:26
Speaker A
But within a function, we have another variable of the exact same name. X equal to 25.
92:32
Speaker A
Then I do Y equal X, and then return Y. So, the existential question here is that when I assign Y equal to X, which X am I looking at?
92:42
Speaker A
Is it the X outside the function, or the X inside the function? Well, what's your guess?
92:51
Speaker A
Let's execute the program and see what happens. Ooh. It seems like it's 25. So, the X inside the function.
93:06
Speaker A
During the function execution process, we always prefer to look at the variable within the sandbox.
93:13
Speaker A
Let me ask a follow-up question. Suppose I change the code, and I remove this line. So, there is no X within a function definition.
93:22
Speaker A
If I still do Y equal to X, can Y find X from line number one, or this program would lead to an error?
93:34
Speaker A
Let's find out. Y equal to X, but there's no X. So, the function looks outside, and find X in the global scope, and binds Y equal to 1. Seems like the program can indeed find variable outside the function
93:52
Speaker A
definition. These two examples just now highlights an important message. In function execution, we always prioritize variable lookup in the local scope. Only if not found, then we look into the global scope.
94:07
Speaker A
The term local scope is a fancy but professional way of saying everything within the sandbox. And global scope is everything outside.
94:16
Speaker A
Wait a second. Why would anyone write code like this? This feels intentionally confusing. Why do you have to create a local variable with the same name as a global variable?
94:26
Speaker A
Just change it to a unique name and you can avoid all this confusion. Well, I totally agree.
94:32
Speaker A
Almost no one at a tech company will write code like this. But distinguishing between local scope and global scope is important. So, bear with me here.
94:43
Speaker A
Local scope has access to global scope, but the other way around is not true.
94:48
Speaker A
Once again, let me modify the code. On line number nine, rather than print result, I print K, which is defined only within a function.
94:56
Speaker A
What happens? When the program tries to print K, but there is no K anywhere to be seen in the global scope.
95:08
Speaker A
Well, there was a K when the function was executing, but it vanished alongside with the sandbox.
95:14
Speaker A
So, this program actually give you an error. Let's talk about interesting topic called function composition.
95:22
Speaker A
I have two function here. Function F takes input R and compute pi r squared.
95:28
Speaker A
You might notice that's the formula for area of a circle. Function G simply multiply four for its input.
95:35
Speaker A
What's so special about the four here? It's because the surface area of a sphere is actually four times the area of a circle projection. So, if someone asked me, what is the surface area of a sphere that has radius five? I can first
95:48
Speaker A
compute the area of a circle whose radius is five and store into variable A. Then the function G multiply A by 4.
95:55
Speaker A
This gives me the surface area of that sphere. This is very good. But you might wonder, since A is just a return value of of f of phi, why can't we just pass f of phi directly as an input for the function G? And this
96:09
Speaker A
would actually make our code more concise. Yes, you can. But why is that? In Python function call, you always evaluate the input before jumping to the function execution.
96:20
Speaker A
Evaluate is kind of my fancy way of saying, if the input in my function is actually another function call, I got to figure out what is return value of the inner function first.
96:31
Speaker A
This is what it looks like. We first evaluate the function f of phi. It returns 78.5.
96:39
Speaker A
And that becomes the input to the outer function G. And then the function call for G happens.
96:49
Speaker A
I can even exaggerate this idea by showing you a triple nested function call. But you already know what happens here.
96:55
Speaker A
We're calling function H. But what is the input? It's clearly not a number, but rather another function call. So I need to evaluate its input G of f of phi.
97:04
Speaker A
In order to do that, I need to evaluate function G. But I need to evaluate f of phi first.
97:10
Speaker A
You see, the process is almost like me peeling an onion until we get to a function call that's not nested. And then it works its way backwards. When we chain multiple functions together like this, it's called composition.
97:23
Speaker A
And the idea of function composition actually originates from math, not programming. For many difficult concepts in math, I find myself only to truly understand them after I learned programming. Where I try to explain mathematical concepts through the lens of Python.
97:38
Speaker A
In high school, the math class start teaching you about function composition. You probably see something like this.
97:43
Speaker A
And you already know, the next thing the question is going I'm going you is, what is f of g of 20?
97:49
Speaker A
After learning programming, this question is almost trivial. I first define f like the way it's written in the question, and then I define g, and then I define f of g, and simply I call f of g on 20.
98:02
Speaker A
That's the answer. Programming in essence is mathematics in action. If this feels déjà vu to you, you're probably thinking about chapter 6, where we said the scary sigma notation is really just a for loop in Python.
98:19
Speaker A
In the last two videos, I've been using the word inputs a lot when describing the thing that enters a function. I didn't want to detour the lesson by spending too much attention on terminology. The more professional terminology for input is actually
98:32
Speaker A
arguments for the function. Very interesting choice of word right there. Cool. Today's lesson is a bit tedious. I want to end it with a quote from a legendary programmer called Terry Davis.
98:42
Speaker A
Idiots admire complexity. Genius admire simplicity. Terry is a bit of a controversial figure, but I do agree with this sentence here.
98:51
Speaker A
Programming is not about writing fancy and convoluted code to impress your peers. Programming is about writing the simplest and readable code, so everyone can tackle the same underlying problem together. Let me give you an example. If I were to look at this code, I won't be
99:05
Speaker A
able to figure out what's going on. I see there's a for loop, but there's so many things happening within the for loop, which makes it difficult for my brain to render what's the intention behind. But the very identical logic
99:18
Speaker A
when written differently can be instantly readable. Look at the improved version here. You see the programmer first break down the big problem into multiple small function definition, and simply by reading the name of function, you can gauge into its
99:30
Speaker A
underlying purpose. And there's documentation. The goal is to buy stocks based on Google search trend and sentiment analysis based on news article.
99:39
Speaker A
We have a list of potential candidates. For each candidate, we check its Google search trend. If there is momentum in search volume for last 3 hours, it passes the first round check as a trendy stock.
99:51
Speaker A
Then, for the surviving trendy stock, we fetch all the news from today about that stock and ask GPT to rate a score from 0 to 10. If the score is more than 7, then we buy it. And this is good code. This
100:03
Speaker A
is what peak programming looks like. It pipeline multiple functions together rather than trying to do everything in one place. It feels like you're no longer reading computer code, but you're reading human language.
100:19
Speaker A
Today, we talk about a slightly advanced topic, value versus reference. A quick review. When we do variable assignment for number and string, we assign by making a copy of the value.
100:30
Speaker A
This is a correct mental picture. Variable B takes on the value of 7, but a common mistake is this one. In which people imagining the assignment makes variable B becoming variable A itself.
100:43
Speaker A
This is the incorrect mental picture to have. With this understanding, we know that if later on I reassign variable B to something else, variable A is still untouched. If I print A, it still prints 7.
100:55
Speaker A
Cool. So far, so good. If the variable is number or string, we know what happens. But, what about Python list?
101:03
Speaker A
Previously, I foreshadowed that when I create a list, my variable is a reference towards a list. Rather than my variable containing a list, I never explained why. So, what is your mental picture when I do list assignment? Is it
101:17
Speaker A
this one? Do I create a reference to the same list? Or this one? I make a copy of the Python list.
101:25
Speaker A
And surprisingly, we don't make a copy. The new variable would have the same reference to the original list. And this has a profound implication.
101:34
Speaker A
Let's say if I change the second element of list B, I will first follow the reference pointed by list B, and then modify the second element. But you see, since the list A also reference towards the same data, my modification on B has
101:48
Speaker A
unintentionally affected A. If I print A, it's no longer 1 2 3. You see, assignment of list very much forms a stark contrast with number and string.
101:58
Speaker A
For number and string, you assign a new variable by making a copy of the value.
102:03
Speaker A
Changing the new variable has absolutely no impact on the original one. For list, you make assignment by reference.
102:10
Speaker A
Changing the new variable induce mutation on the original one. Next, let's up notch the difficulty by bringing function call into play. But don't worry. I promise you that nothing had fundamentally changed from just now.
102:24
Speaker A
So, what I have here is that I have a function f of x. The function increased the value of its input by one, and doesn't have return statement.
102:34
Speaker A
And then, I create a variable with k equal to 10. I call the function f on k.
102:39
Speaker A
So, if I print k, am I going to see k becoming 11? But first, let me ask you, what's your mental model?
102:46
Speaker A
When I pass the variable k as input to function f, are you imagining something like this?
102:51
Speaker A
The value of k, which is integer 10, enters the function. Or is your mental model the variable k itself entering the function?
103:02
Speaker A
The quick answer, not surprisingly, is the former. Just like a variable assignment, for string and number, it's the value that gets moved. Let's execute the code to confirm.
103:13
Speaker A
Since the input is really the value of 10 entering the function, but not the variable k, if I increase 10 to 11, that has no business to do with the original k.
103:23
Speaker A
After the function call, if I print k, I still get 10. What about if a variable is a list, and we're passing it to a function? Which one would it be?
103:33
Speaker A
Are you passing the reference to the list to the function? Or are you making a copy of the list?
103:40
Speaker A
You guessed it. We're passing the reference because the variable is a list. Let's see what happens with the code here.
103:49
Speaker A
The function's input has the same reference to the list V in the global frame.
103:54
Speaker A
The function modify element zero to be 99. And then it append a new element.
104:00
Speaker A
After the function call terminates, the original list V is no longer the same. At this point, the elephant in the room is why.
104:10
Speaker A
Why do we have this complex rule and the intricate difference between value and reference?
104:14
Speaker A
Why can't we always just make a copy all the time? So, we never need to worry about reference.
104:20
Speaker A
And that's a wonderful question. I'll first try to explain with analogy. And then a more involved second explanation from a computer hardware perspective.
104:32
Speaker A
Suppose you read an interesting article on your phone. And you want to share with your friend. You have two options.
104:38
Speaker A
One, you type every single word verbatim as a text message. Or two. You can just share the link to the article.
104:48
Speaker A
Well, preferably we would do the latter. We don't want to spend time typing down the text. Because the article is really long. We just want to swiftly send the link. And we know that our friend just need to click open the link. The link is
105:01
Speaker A
just like a reference in Python. A reference is lightweight. And passing them is easy and fast.
105:07
Speaker A
Most Python lists in real programming setting, they're very, very long. Containing millions and billions of elements.
105:14
Speaker A
We can't afford having computer making copies of so many elements. Because making copies data actually take time.
105:20
Speaker A
Now, let's dive into the second explanation from a computer architecture perspective. Why does Python and many other language use a reference?
105:29
Speaker A
Inside your computer, we have two key players, the CPU and the memory. The dance between them is what make your code actually run.
105:38
Speaker A
Down here, we have the heap memory. This is where large data lives, like Python list.
105:44
Speaker A
For example, a list that contains the entire book of Harry Potter sits right here.
105:51
Speaker A
And near the top, we have the stack memory, where function do their magic. When a function runs, it needs information about its input within the stack memory. Now, we could copy the entire list from the heap into the
106:04
Speaker A
stack. But look at this. It's slow, it take extra space, and worst of all, we're duplicating data we don't even need to change.
106:13
Speaker A
Instead, we could do something smarter, which is put a reference in the stack, a tiny pointer, like a sticky note saying, "Hey, look down there." The CPU then follows the reference to the heap, grabs the actual data, and get
106:27
Speaker A
to work. Cool. Hopefully, you're starting to see why references matter so much in programming.
106:34
Speaker A
So for now, here's a simple rule you can hold on to. Lightweight data types, like numbers and string, are passing by value.
106:41
Speaker A
But heavyweight types, like list, dictionary, or class objects, are passed by reference. It's not a hard rule in every language, but in Python, this general intuition will take you pretty far.
106:55
Speaker A
Python dictionary, perhaps one of the most useful data structure, in my opinion. Previously in chapter four, we learned Python list, which can store a collection of many arbitrary data. List is also versatile for its operation. We can easily access,
107:11
Speaker A
modify add remove its element. And most importantly, this is an iterable, which allows us to run a for loop. If Python list is so awesome, why do we need dictionary?
107:26
Speaker A
A dictionary is all about relationship between piece of data. And it turns out we really care about those relationships. Think about it. If you're a football analyst, you don't just care about how many goals Messi or Ronaldo score in total. You care about how many
107:40
Speaker A
goals they score in a specific year. For example, in 2015, how many goals Messi score?
107:47
Speaker A
If you're a software engineer at Uber Eats, you care about the name of a dish and its corresponding price. If someone order a pizza, how much does it cost?
107:58
Speaker A
If you manage inventory at Costco, you probably want a data structure that track the name of item and the quantity left. How many dried mango we have?
108:07
Speaker A
Should we restock? In all these cases, you're mapping one piece of information to another. You're saying, given this, tell me that.
108:18
Speaker A
This is exactly what Python dictionary do. You provide what's called a key to a dictionary. The dictionary finds the key and it gives you back the corresponding value.
108:30
Speaker A
And the beauty is that the key is meaningful. The key is readable. Compare that to a list, where you're stuck with using the index to access the element. The index has to be a number.
108:42
Speaker A
It does its job, but not as expressive. Potato is now a software engineer at McDonald. Today he's working on digital menu. Let's help him out.
108:53
Speaker A
Potato wants to use the Python dictionary to store the meals and its price. So, he can easily look up the price for particular meal. In this case, the key is the name of the meal, the value is the price.
109:07
Speaker A
To create a dictionary, we use the curly bracket on our keyboard, not the square bracket, because square bracket is already used for Python list. Dictionary fundamentally just store a collection of many key-value pair. Let's first see how we can create one key-value pair.
109:23
Speaker A
We write the key, colon, and then its corresponding value, and finish it off with a comma.
109:31
Speaker A
Now, we can use Big Mac to access its corresponding price. Next, we just need to apply the same syntax for other pair.
109:39
Speaker A
Execute. Here is our dictionary. I want to make a remark that you can also just create an entire dictionary on the same line like this. Either way works. Your pick.
109:50
Speaker A
Next, we're going to learn about the four primary operation for dictionary, which are still access, add, modify, remove.
110:02
Speaker A
A customer wants to buy a Big Mac, but how much does a Big Mac cost? The syntax for accessing the value is as follows.
110:09
Speaker A
We put the name of the dictionary, menu, and square bracket. Within the square bracket, the string Big Mac.
110:16
Speaker A
Doing this, the variable P will bind to the value of 5.99. The key has to match precisely. One of the most common bug is people misspelling the key.
110:27
Speaker A
One interesting thing you might notice, when we access the value, we're using the square bracket, despite a dictionary was created with a curly bracket. When I learned Python, I also find this unintuitive, but this is just how Python's creator, Guido van Rossum, made
110:42
Speaker A
dictionary. We will just have to follow his rule. Once in a while, seasonal special item ushers in. The Shamrock is a minty flavor drink only offered around St.
110:53
Speaker A
Patrick's Day. Let's add it to our dictionary menu. The syntax is on the left-hand side of equal sign, we have the dictionary name, menu, square bracket, the key, Shamrock, equal to its new value, 3.89.
111:07
Speaker A
That's it. Here it is. Next up, we have modification of existing key value pair.
111:16
Speaker A
Due to inflation, McDonald has decided to change the price of its popular item Big Mac to $10 and double the price of french fries. On line number 11, we write menu square bracket Big Mac equal to 10. This update Big Mac to $10.
111:34
Speaker A
But for french fries, we're doubling its price, so it depends on the current price.
111:39
Speaker A
Menu of french fries is equal to the current menu of french fries times two.
111:48
Speaker A
You see, the syntax for modification is identical to addition. If you give the dictionary an existing key, it modify its value within.
111:57
Speaker A
If you give the dictionary a new key, then it adds the key value pair.
112:02
Speaker A
As Saint Patrick's Day pass by, seasonal offering stops. It's time to remove Shamrock from the dictionary, oh, I mean menu. The syntax is menu.pop parentheses the key you want to remove, which is the string Shamrock in our case.
112:19
Speaker A
Now, the Shamrock key value pair vanish from the menu. Dictionary is versatile. I can create a dictionary, the key is number and the value is string.
112:32
Speaker A
Vice versa, the key can be string and the value is number. I can also create a dictionary, the key is string and the value is a Python list.
112:43
Speaker A
The value of dictionary can even be another dictionary. This dictionary maps the name of restaurant to its menu, which in turn is another dictionary.
112:54
Speaker A
Let me show you how I can access a value from something like this. I do restaurant to menu with a key Chick-fil-A and its value is this inner dictionary here.
113:04
Speaker A
Immediately after, I do another value access with a key of waffle fries to retrieve its price here. Variable P will bind to 2.49. You almost have unconstrained freedom with the creation of dictionary. Yet, there's one restriction. The keys of a dictionary
113:21
Speaker A
cannot be a Python list or dictionary. If I try to create a dictionary with a list as key, I would see this following error message. The precise explanation is outside the scope of essence of Python, but you can sort of guess
113:35
Speaker A
roughly why we can do this. Dictionary is just a collection of key-value pairs. If my key is a Python list, and as we know, the contents within a list can change easily. So, our key can change.
113:47
Speaker A
If the key changes, it no longer unlocks its corresponding value. But, the reason we love Python lists is because it's an iterable, which allows us to run a for loop. At this point, we know that loop is basically a superpower
114:01
Speaker A
in programming. Dictionary, luckily, is also an iterable. However, doing a for loop with dictionary is nuanced because dictionary has both keys and values. We need to be careful and precise about what we're doing.
114:16
Speaker A
The keys method returns an iterable of all the keys in the dictionary. This lets us to loop through just the keys and do something with each one, like printing them out.
114:31
Speaker A
Similarly, the value method returns all the values in the dictionary, which we can loop through in the same way.
114:41
Speaker A
You might ask, "What about loop over both the key and value simultaneously?" And yes, that's possible. You'll need the items method and use two separate loop variables. The first one, K, is key. The second one, V, is value. Here's
114:56
Speaker A
what the loops looks like. >> Cool. Let's put it to use. Another customer, Patrick, enters, asks if we have something called Krabby Patty in the menu. We write string Krabby Patty in menu false, so we don't have it.
115:22
Speaker A
Here, I'm also showing you interesting property of Python dictionary. If you don't specify dot keys or dot values, Python would automatically assume you're using dot keys.
115:33
Speaker A
Patrick then asks, "What do you have?" So, we iterate through all the keys and print each one of them. By the way, you know the dot keys here can be optional.
115:44
Speaker A
Patrick says he only has $5, what can he buy? We use the dot items method and iterate through the keys and values simultaneously. Within the loop, only if the value is less than five, we print the key-value pair.
115:57
Speaker A
Execute. Nice. Everything affordable for Patrick here. For our final coding example today, let's try to combine various technique and data structure we learned from previous video together to truly show the charisma of Python dictionary.
116:12
Speaker A
So, you probably heard about the novel and movie series called Harry Potter. We're going to use Python to count how many times a certain name appear in the first novel. You might ask, "What's the point of doing this?" Well, I can argue
116:25
Speaker A
that the importance of a character is proportional to how many times his or her name appear in the novel.
116:30
Speaker A
Intuitively, we know that the name Harry will appear the most, but exactly how many times? And what about Ron, Hermione, Malfoy? Who is the second most important character? Let's find out with Python dictionary.
116:44
Speaker A
I have a Python list called book, which contains every single word of the first novel.
116:50
Speaker A
It has 78,000 words. My coding strategy is that I will initialize a dictionary with a character's name as a key and zero for all their value.
117:01
Speaker A
The dictionary will store how many times I've seen a character in the novel. I will iterate through every single word in the book. If the word match any character's name, then I'll increment that name's value in the dictionary by
117:14
Speaker A
one. Let's execute the code. And I print dictionary. Harry appear 1,200 times and then we have Ron, Hermione, and last Malfoy.
117:26
Speaker A
This kind of roughly aligns with my expectation. And also, just notice how fast Python is. The for loop completed the entire book almost instantaneously.
117:36
Speaker A
If you felt this code here is a bit complex, I understand. Here is its equivalent visualization.
117:42
Speaker A
This loop diligently examine every single word, increment the dictionary if necessary. For example, now the loop variable binds to chapter.
117:52
Speaker A
Chapter is not in the dictionary, so the if statement doesn't get triggered. The word then binds to one, which is also not in the dictionary and the if statement doesn't get triggered.
118:02
Speaker A
Honestly, this loop is going to run for a while and don't find anything meaningful until much later.
118:09
Speaker A
The word binds to Harry. Harry is indeed in the dictionary, so I increment Harry's value by one.
118:21
Speaker A
The loop runs, runs, runs, runs. And it finds Harry again. Harry's value increments by one.
118:31
Speaker A
So, you can imagine when this loop gets to the very last word of chapter one, the loop would have counted everyone's name correctly into the dictionary.
118:41
Speaker A
Also, remember everything you saw just now happens in less than a second. That's just how fast Python is.
118:57
Speaker A
>> You embark on a journey seeking for the truth and the wisdom of programming. You learn various technique and data structure. Now you can write code which computes the factorial of any integer using a for loop iterating over positive
119:11
Speaker A
integer from 1 to n. The loop variable accumulates the product along the way. When the loop completes, you get your factorial.
119:21
Speaker A
This is no small achievement, but you keep going learning from friends and sensei because you believe there's another gem out there waiting for you.
119:31
Speaker A
However, the journey is harsh. For a long time you believe some kind of loop is the only way you can compute factorial and there's nothing more out there.
119:40
Speaker A
Until one day, you climb a mountain and met with an old wise monk. You told him about your mission seeking for the elegance of programming.
119:49
Speaker A
He smiled and asked you, >> Can you tell me what's the factorial of five?
119:54
Speaker A
>> Oh, that's simple. It is 5 * 4 * 3 * 2 * 1.
119:58
Speaker A
>> How about factorial of six then? >> That's just 6 * 5 4 3 2 1.
120:03
Speaker A
>> You notice something interesting. What is this part? >> That's just 5 * 4 3 2 1. Oh wait.
120:10
Speaker A
This is the factorial of five. So, the factorial of six is the integer six times the factorial of five.
120:18
Speaker A
>> Very well. Can we generalize for all number? >> Should be the factorial of n is the integer n times the factorial of n minus 1.
120:28
Speaker A
>> Good. Take out your keyboard. Define function factorial. What is the factorial of one?
120:34
Speaker A
>> It's one. No question asked. >> Else? >> We said that it's the number n times the factorial of n minus 1.
120:41
Speaker A
Wait, wait, wait. I'm still defining the function. How can I be using the function?
120:46
Speaker A
>> Don't worry. Give it a try. It's about the recursive leap of faith. >> Well, let me try.
120:54
Speaker A
The factorial 5 is indeed 120. This function actually work. Wow. If today is your first time seeing a recursive function, you should be amazed and confused.
121:06
Speaker A
So, let's slowly take a look at what happened. We're calling the function fact, short for factorial, on five. It checked the if statement and is not one.
121:15
Speaker A
So, we entered the else case. But now, it's n multiply with another function call of itself. It's calling fact of n minus one, which is factorial 4.
121:25
Speaker A
So, it creates a new function frame with n of the exact same definition, but this time, the input n is 4.
121:32
Speaker A
It failed the if statement and goes to the else case. It's calling n times fact of 3.
121:38
Speaker A
So, it opens another function frame with input of 3. Similar logic happens here. Fact 3 is going to call n times fact 2.
121:49
Speaker A
And factor 2 is calling factor 1. Okay. Here, the if statement finally pass. We hit the base case. The function frame returns 1. But what do we do with this value 1 here? It's getting sent back to its parent function frame here.
122:07
Speaker A
Now, the parent function frame, fact 2, can fully evaluate the return statement, n times 1, which is 2 times 1, and the value 2 is sent back to its respective parent frame, which it will evaluate 3 times 2, 6,
122:24
Speaker A
and 6 is sent back to its parent frame, which it would evaluate 4 times 6, 24.
122:31
Speaker A
Finally, we go back to the original function frame, which returns 5 times 24, 120. That was a lot to digest. But if we were to reflect on what just happened, it's kind of like we were peeling an onion layer by layer until we
122:47
Speaker A
arrive at a base case. And then, its return value gradually pass all the way back up.
122:56
Speaker A
The factorial function is the poster child of learning recursion because it demonstrates three important principles.
123:03
Speaker A
One, the function intends to call itself during definition. This fears that the function is trying to solve a problem using itself. This might also be the most unsettling part to look at because you might wonder, wouldn't this just
123:16
Speaker A
lead to an infinite chain of a self calling self calling self? Two, the function has a base case, which is how does it handle the smallest problem size? For example, the factorial of one is just one. No one's going to
123:29
Speaker A
question that. The base case is how the function prevents an infinite recursive call. Three, the function has recursive case, which helps to gradually reduce the problem size. This is the most critical part of recursive function. Notice, while calling the function itself, the
123:46
Speaker A
argument is no longer factorial of n, but factorial of n minus one. Without doing this, your recursive function would never get to the base case.
123:56
Speaker A
These are the three characteristic you need to remember by heart when designing your own recursive function.
124:03
Speaker A
So, let me show you another example of recursive function and see how the three principles still apply. The goal here is to design a function which can reverse a string. For example, ABCD turns into DCBA.
124:16
Speaker A
Generally, when solving a recursive problem, it takes quite a bit of poking around with experimental trial and error.
124:23
Speaker A
Let's say I have ABCD here and I want to reverse it. Here's an observation I have. When a string is reversed, its original first character will become the last character.
124:35
Speaker A
So, I can try to break the string as the first character A and then everything else after it.
124:42
Speaker A
If someone else can magically reverse BCD, then I just need to stick the character A at the very end and the string's reversed. Simple.
124:52
Speaker A
But how can I reverse BCD? Well, I can use the same process. I can break into B and CD, the first character and then everything afterwards.
125:02
Speaker A
If someone else can reverse CD into DC, then I just need to put the B at the very end.
125:10
Speaker A
Well, you notice I'm using the exact same problem-solving methodology, but just on a gradually smaller problem size. I am reducing a bigger problem into a smaller problem and using the very same algorithm to solve the smaller problem. Recursion is screaming to be
125:25
Speaker A
used. I define the function reverse. First, the base case. If we just have one character, then nothing needs to be reversed. It is just itself.
125:36
Speaker A
Else, if the string is longer, all we need to do is to take the first character and put it at the very end.
125:44
Speaker A
And I'll call the reverse function on the substring from index one. When I'm calling the reverse function, I'm implicitly trusting it to return the correct results to me.
125:55
Speaker A
I am trusting it to correctly reverse a substring so I can combine it with the first character later on.
126:02
Speaker A
I am confidently trusting this function call even though it seems untrustworthy because I'm still in the process of defining the function.
126:09
Speaker A
And this unceremonious trust is the essence of the recursive leap of faith. It's a secret covenant between the programmer and the recursive function.
126:22
Speaker A
If a visualization helps you to solidify the understanding, here's how the reverse function looks like.
127:24
Speaker A
>> Today's video is an informal tourist guide to the concept of recursion in programming.
127:29
Speaker A
Recursion is often one of those topics with an infinite rabbit hole and very high skill ceiling. This video alone cannot make you a recursion master. I'm here to spark your interest by programming and share something I personally find very elegant when I was
127:44
Speaker A
learning Python in college. Let's end the video on a quote. Beauty is everywhere. It is not that she's lacking to our eye, but our eyes which fail to perceive her. But really, I can change the word beauty into
127:57
Speaker A
recursion because recursion is everywhere in our life and in computer science. It's our programmer's duty to perceive them.
128:09
Speaker A
My plan for the future is that hopefully one day I can make educational video full-time. The potential candidate for my next courses are operating system, computer architecture, large language model full stack.
128:23
Speaker A
Nowadays, YouTube is populated with contents of high production value. Yet, you chose to sit through 14 episodes of Essence of Python to learn about coding.
128:32
Speaker A
You don't know who I am, and I don't know who you are. Much like two strangers going on journey together.
128:38
Speaker A
This reminds me of my favorite anime, Samurai Champloo, which tells such a story. The three main character, Jin, Mugen, Fu, have never met, but they went on a journey from Edo to Nagasaki seeking for samurai with a scent of
128:52
Speaker A
sunflower. And this anime has quite a beautiful ending song, Shiki no Uta. I'd share that with you, and let's end on that.
129:05
Speaker A
>> [music] [music] [music] [music]
Topics:programming thinkingPython tutorialvariables in Pythoncontrol flowloopsfunctionsrecursionAI and programmingvalue vs referencecoding fundamentals

Answers

Frequently Asked Questions

Why is programming thinking still important with AI?

Programming thinking helps you ask better questions and maximize AI's potential, making it essential even when AI can write code.

Can Python variables store different data types?

Yes, Python variables are flexible and can store any data type, changing their stored value throughout program execution.

What is the difference between value and reference in Python?

Value refers to the actual data stored, while reference is a pointer to the data's location in memory, affecting how variables interact and change.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →