03 Procedural Programming: Introduction to variables and control flow
Introduction to variables and control flow
Let’s look on the following program:
{01_variables1.py}
If you go to 03_procedural_programming directory and type python 01_variables1.py,
you will see on your screen 5. Let’s go line-by-line as interpreter will do and try to understand what happens here.
Actually while first line seems very short, there a lot of happening under the hood. Let’s try to describe simplified version first. 2 is constant integer, so we’re assigning 2 to the variable first.We can also say that first “holds” value 2.
I will use following simplified model: CPU or processor is computational unit responsible for computation. There is also some “pointer” on what line is currently executed, this pointer is generally goes up (from 1 to 4 in the program above). There are 2 types of memory: heap and stack.
In general, every object (and in Python everything is implemented as object) is created on heap, but pointer to this object can be saved both on heap and on stack.
For now, ignore, the stack part. First is global variable. This means, it is accessible in every place in the source file (in order to change it, you will need some extra command, though). So, interpreter see at runtime 2, this is int (constant & integer) value, it creates int object at the heap and saves pointer to it in variable called first.
So, what is variable in Python? It is just reference to the objects defined on heap or stack. The type of the first variable is known only at runtime and only after initialization. This is known as dynamic type.
So, first is (global) variable that points to object 2 and has (dynamic) type int.
Note: We didn’t see another type than global variables yet, but this concept is pretty straight-forward, what is less straight-forward is dynamic type. In C, for example, all types are static. I will get back to this distinction later.
There are some restrictions on what is allowed to used in variables name. First of all, a variable name can only contain alpha-numeric characters and underscores (A-z, 0–9, and _ ). Variable names are case-sensitive (age, Age and AGE are three different variables). A variable name must start with a letter or the underscore character. A variable name cannot start with a number. It is better to use descriptive name such as first argument, second argument, result and not a short name, like a,b,c.
In the second line, we’re defining variable/reference to the int 3 object.
In the third line, we executes first+second
part first, we get new object (that holds int 5) on the heap and reference to it is assigned to result variable.
Than we print the result variable on the screen.
So, we get 5 as expected (5=2+3)
.
Let’s look on the slight variant of the same program:
{02_variables2.py}
Here, as you can see first 3 lines are identical to the previous program, but instead of printing only 5 to the screen, we’re providing more information, that actually, it is the result of 2+3
. But why, we use 6 lines to print something trivial like this? And what is end=’ ‘
in each print
command?
“The result of” and first has different types. “The result of” is what is called Python String and first is int. print command knows how to print both int and String, so here, I just spited up the sentence where in each line I have or int or String. By default, print command also prints “new line”, specifying end=’ ‘
is saying to use blank instead “new line”.
Note: Many of you’re screening on me, that it is wrong to call print “command”, that this a function. But we didn’t learn functions yet. So, I don’t want to use this word.
So, line 4 print to the screen “The result of “, than line 5 adds “2 “, than line 6 adds “+ “, than line 7 adds “3 “, than line 8 adds “is “, than line 9 adds “5” and we have result “The result of 2 + 3 is 5”.
It looks like too much effort to something simple like this. We’re anticipating, that we can express in one line the sentence written above. Let’s try something like this:
{03_variables3.py}
If we will run this, we will get the following message:
Traceback (most recent call last):
File "/opt/project/IntroCS/03_procedural_programming/03_variables3.py", line 4, in <module>
print("The result of"+first+" + "+second+" is "+result)
TypeError: can only concatenate str (not "int") to str
Clearly, we didn’t get the message we wanted. What we’re looking for, is example of uncaught error/message. We will learn about this later. For, it is suffice to understand that Python
can only concatenate str (not "int") to str
that is “Hello, ”+”World!”
(this is concatenation of String to String) is ok, 2+3
is ok (this is sum of two integers), but “The result of “+2 Python don ‘t know how to deal with.
Note: We’re using the same symbol + both for
int + int
(sum) andString+String
(concatenation). The semantic of + is different and depends on the type.
We can use, the simple trick to fix this. See
{04_variables4.py}
str()
is built-in “command” that can convert almost any type to String
. So, here in line 4 we have concatenation of only String
s and this is allowed.
But, this style steal has the problem. Let have a closer look.
When we have first concatenation
"The result of "+str(first)
new intermediate object is created, than this newly created object is concated with str(second)
, second intermediate object is created, than it is concatenated with str(result)
for the third time. Each +
sign we’re creating intermediate objects.
Can we somehow, created the String with one pass? Yes, we can! In Python there is something that is called f-String
or formatted String
. This is how the code will look like:
{05_variables5.py}
Here, we have one long String (+ is just a symbol in the String like T), and in {} we can specify variables, each value can be substituted with. For example, instead first we will see 2. This is done, without creating many intermediate objects. After all replacements are done (in runtime), the result is ordinary String
. Search for “f- String” for more details.
Now, let’s write some very simple test program. This program will ask, how much is 2+3, it will get the input from the user, and if the user is right, it will print “You’re right!”, and if the user if wrong, it will print “Sorry, you’re wrong.”
Note: To make thing simple, I’m ignoring exceptions.
{06_variables6.py}
First 3 line is as above.
In the line 4, I’m using f-String to create phrase “How much is 2 + 3?” This is preferable way for writing. If later, we will change the value of first or second we can leave the line 4 unchanged. input()
built-in “command” types this phrase on the screen and than waits for input. Whatever you will type (after pressing enter) will be put to variable answer. You should put only int
values their (see note above). In line 5 I’m using built-in “command” int(some_value)
to change the type to int
. Result
hasint
type. If we want to compare to it, we should compare int
-s. Otherwise, user’s answer will be always not the same as computed.
Note: As you see, while you don’t have to write types (but you can, if you want to)), while you have dynamic typing, you still should care about correct type of the objects.
Lines 6–9 is what is called branching operator. First it evaluate the value after if, whether result equals to answer (==
is used, because =
is used for assignments, such as first=2
, just not to be confused). For the int
objects it does it by checking actual value.
If in line 4, you will type 5, than in line 6 you will check, whether 5==5, that is obviously true, for any other value, you will get — false.
Note: In Python boolean has only 2 values —
True
andFalse
.
Depending whether value if statement get True
or False
only one brunch will be executed. If True
— the first brunch, that prints “You’re right!”, if False
— the second brunch, that prints “Sorry, you’re wrong”.
After neighter of branches is executed, executions continues from line 10 — first statement after if branching operator.
Under the hood
You can see, that statements in those brunches are written with 4 spaces (it can be tab instead). This is called indentation, and it is Python way to indicate “brunches” like above. If one of the brunches had more than 1 statement, it had to be identied with 4 spaces, otherwise, the program may crash. See general if branching operator a bit below for clarification.
Note: For impatient readers I have to tell, that in Python if statement doesn’t define new scope. I will about scope, when I will talk about defining functions.
To summarize, there is following form of if branching operator:
if condition:
statament1
statament2
else:
statament3
statament4
statemtent5
- condition is evaluating.
- If it is True, statement1 and statement2 are executed.
- If it is False,statement3 and statement4 are executed.
- In both cases statement5 is executed.
On machine level there is something called “conditional jump”. If condition is True the pointer of the execution of the programs “jumps” to one part of the program, otherwise to another. When each branch ends there “jump” operator to first operator after if block.
There are many variances of if branching operator. Each of them can be expressed with the help of this base if branching operator.
Note: Python has special command called noop — no operator, this command does nothing. Sometimes, you will need it.
This was only introduction for both variable and branching. So, in the next chapter we will have introduction to the importing system of Python.
This story is part of my new book.