Ten commandments of programming
Loops
Comparison and logical operators
Conditionals
First think about what exactly you want to do before writing any code.
Expectation: Break your problem into small independent blocks. Specify precisely what you want each block to do.
Prepare the project, i.e., create a folder and start with a fresh .py file.
Work "Inside to Outside": Identify the "core functionality" in each block, make the core work first, and only then refine and extend.
If necessary, use the internet to get help (google "Python how to ...").
However, do not just copy-and-paste. Understand the main idea and write your own code!
Verification: Test your code line by line as you write it! Your computer always does exactly what you tell it to do. So if the result is different from the expectation defined in Step 2, it's your fault.
Read Python error messages. If you just added one line and the code "doesn't work" anymore, the problem is likely related to this line.
Always put meaningful comments into your code as you write it. Undocumented code is useless!
Be proud of what you achieved. Create a Github profile and share your codes.
In Python 3, we often use the for
-loop together with the range
function which pretends to return a list of numbers (it returns something more complex, we can consider it a list for now). That function can be called as follows:
range(n)
-- numbers $0, 1, \dots, n \color{red}{-1}$; this is equivalent to range(0,n)
;range(m, n)
-- numbers $m, m+1, \dots, n \color{red}{-1}$;range(m, n, s)
-- numbers $m, m+s, \dots, m + sk$, where $k \in \mathbb{N}$ such that $m + sk \color{red}{<} n \le m + s(k+1)$.Do not forget that the ending is not included, hence "$\color{red}{-1}$"!
Python 2 remark: In Python 2, range
actually returns a list. The exact equivalent to range
from Python 3 is called xrange
in Python 2.
for
-loop in action¶Let us make an overly enthusiastic version of the "Hello, World!" program that would repeat its message $5$ times.
for i in range(5):
print("Hello, World!")
Let us read it as if it was a sentence in regular English language, taking into account that range(5)
acts as a list of numbers $0, 1, 2, 3, 4$:
For
i
in [0, 1, 2, 3, 4], print "Hello, World!".
So, this is equivalent to the code:
i = 0
print("Hello, World!")
i = 1
print("Hello, World!")
i = 2
print("Hello, World!")
i = 3
print("Hello, World!")
i = 4
print("Hello, World!")
Obviously, we don't need the variable i
, but it's part of the loop. If we want to ignore it, we can use the underscore _
instead:
for _ in range(5):
print("Hello, World!")
This is the same as
print("Hello, World!")
print("Hello, World!")
print("Hello, World!")
print("Hello, World!")
print("Hello, World!")
for
-loop syntax¶for
-loops have the following elements:
_
" if we don't need those values),Do not forget the colon! This will make Python somewhat nervous...
Notice the indentation in the second line:
for i in range(5):
print("Hello, World!")
All the commands with the same indentation "belong" to that loop. Observe the difference:
print("The first loop:")
for i in range(3):
print("Inside loop.")
print("And where is this? Inside or outside of the loop?")
print()
print("The second loop:")
for i in range(3):
print("Inside loop.")
print("And where is this? Inside or outside of the loop?")
Write a program that inputs an integer $n$, then inputs $n$ numbers $a_1, a_2, \dots, a_n$ and prints $$S = \sum_{k=1}^n a_k.$$
How would we do it manually?
Since computers prefer to know in advance that we wish to loop through some of the code, we shall rearrange the above (i.e., put the item 5 where the loop starts):
We are now ready for a Python code:
n = int(input("How many numbers do you want to add up? "))
s = 0
for i in range(n):
x = float(input("Input a_" + str(i+1) + ": "))
s += x
print(s)
In the above code, we use the variable i
to explain to the user which number they have to input. However, since range(n)
traverses through numbers $0, 1, \dots, n-1$ and we want then to be $1, 2, \dots, n$, we used i+1
for such a description.
We can avoid this extra addition by simply explaining to the range()
function that we want the numbers to start from $1$ and go up to $n$ (i.e., numbers from $1$, strictly smaller than $n+1$):
n = int(input("How many numbers do you want to add up? "))
s = 0
for i in range(1, n+1):
x = float(input("Input a_" + str(i) + ": "))
s += x
print(s)
Usually, the first approach is better because indexing of lists (we'll get to them later) is zero-based and you'll almost always want your loop counter to respect that.
while
-loops¶It is not always known ahead of the execution how many times the loop will have to repeat its block. For example:
Equivalent to the basic for
-loop,
n = int(input("n = "))
for i in range(n):
print(i)
is the following code:
n = int(input("n = "))
i = 0
while i < n:
print(i)
i += 1
Let us, as before, read the above code as if it was a sentence in regular English language, taking into account that i += 1
stands for "add 1 to i
", i.e., "increase i
by 1":
While $i$ is less than $n$, print $i$ and increase it by one.
And this is exactly how while
-loops work:
while
-loop syntax¶while
-loops have the following elements:
As with the for
-loop, do not forget the colon!
Before each execution of the body, and only then!
Observe the following code:
i = 0
while i < 2:
print("Before the increment:", i)
i += 1
print("After the increment:", i)
So, even after i
took the value 2 (thus, making the condition i < 2
false), the body still executed until the end, before rechecking the condition and terminating the loop!
Yes, we can break the loop earlier than it would normally stop and we can skip parts of it. This will be addressed later on, along with other methods of changing the normal flow of control in programs.
These are the comparison operators that can be used on numbers (and some other types, for example strings):
Operator | Example | Meaning |
---|---|---|
< |
a < b |
The value of a is smaller than the value of b |
<= |
a <= b |
The value of a is smaller than or equal to the value of b |
> |
a > b |
The value of a is bigger than the value of b |
>= |
a >= b |
The value of a is bigger than or equal to the value of b |
== |
a == b |
The value of a is equal to the value of b (but not necessarily identical!) |
!= |
a != b |
The value of a is not equal to the value of b |
is |
a is b |
a and b are exactly the same object |
is not |
a is not b |
a and b are not exactly the same object |
or |
a or b |
a is true or b is true (or both); a and b can be non-Boolean values |
and |
a and b |
Both a and b are true; a and b can be non-Boolean values |
not |
not a |
True if a is false; False otherwise; a can be a non-Boolean value |
When checking if the value of a variable x
is undefined (i.e., it is None
), always use x is None
or x is not None
, and not x == None
or x != None
(the reasons are quite technical and far beyond the scope of this course; those interested can read more about the subject here).
Also, do not use not x is None
or not (x is None)
; instead, use a much more readable x is not None
.
As we have seen, a < b
is True
if a
is less than b
and False
otherwise:
print("1 < 2:", 1 < 2)
print("1 < 1:", 1 < 1)
print("2 < 1:", 2 < 1)
In Python, we can also use
a < b < c
as a shorthand for
a < b and b < c
and
a < b > c
as a shorthand for
a < b and b > c
as shown below:
print("1 < 2 < 3:", 1 < 2 < 3)
print("1 < 2 < 1:", 1 < 2 < 1)
print("1 < 2 > 3:", 1 < 2 > 3)
print("1 < 2 > 1:", 1 < 2 > 1)
Of course, all of the comparison operators can be used (do try to not sacrifice the code readability):
a = 1
b = 2
c = 2
d = 0
print("1 < 2 == 2 >= 0:", a < b == c >= d)
print("1 < 2 == 0 >= 2:", a < b == d >= c)
print("1 < 2 >= 2 > 0: ", a < b >= c > d)
print("1 <= 2 >= 2 > 0:", a <= b >= c > d)
However, be very careful in other languages: the form with more than one comparison will be accepted by almost all of them, but it will not work as one would expect (like it does in Python)! This affects C/C++, MATLAB, PHP, PERL, Java, JavaScript,... It does work as expected in Mathematica. In R, it won't work at all (but at least it will report an error).
The equality ==
and inequality !=
operators ignore the types of data to a certain extent. For example,
print("False == 0:", False == 0)
print(" type(False):", type(False))
print(" type(0):", type(0))
print(" type(False) == type(0):", type(False) == type(0))
print("True == 1:", True == 1)
print(" type(True):", type(True))
print(" type(1):", type(1))
print(" type(True) == type(1):", type(True) == type(1))
print("True != 2:", True != 2)
print(" type(True):", type(True))
print(" type(2):", type(2))
print(" type(True) == type(2):", type(True) == type(2))
Some languages (like PHP and JavaScript) have a strict equality operator ===
and strict inequality operator !==
that check both types and values of the compared objects. However, Python doesn't have that.
We have seen how to say
While some condition is true, do this.
However, we don't always want to repeat doing things. Sometimes, we want:
If some condition is true, do this.
This request leads us to conditionals.
A conditional is created with if
statement and it is very similar to while
-loops, with the main difference being that its block will be executed at most once (if the condition is true).
Since the execution of the body is not repeated by the if
statement, there are two possible branches:
However, sometimes, we want to say
If
condition1
is true, dojob1
, else ifcondition2
is true, dojob2
, else dojob3
Here is an example of all three of these:
n = int(input("Input an integer: "))
if n < 0:
print("Number", n, "is negative.")
elif n > 0:
print("Number", n, "is positive.")
else:
print("Number", n, "has an identity crisis!")
Notice how else if
is abbreviated to elif
. This is to avoid too much indentation. Without it, we'd have to write:
n = int(input("Input an integer: "))
if n < 0:
print("Number", n, "is negative.")
else:
if n > 0:
print("Number", n, "is positive.")
else:
print("Number", n, "is a rebel!")
As before, all the controlling parts of a conditional (if condition
, elif condition
, and else
) need to end with a colon!
Of course, we can stack as many elif
parts as we need (including none of them), and we can omit the else
part if we don't need it.
else
with loops¶In Python 3, it is possible to use else
in conjuction with loops. However, it is an unusual construct that other languages do not use and is best avoided by new programmers. At this point, we haven't covered enough of Python to explain what it does.
So be careful not to write
while condition1:
if condition2:
some_code
else:
some_code
instead of
while condition1:
if condition2:
some_code
else:
some_code
as Python will not report an error. It will instead do something, but not what you wanted.
We shall cover loops' else
statement later on in the course.
Give two variables a
and b
, find which one is the minimum and which one is the maximum. Store those values in variables min_value
and max_value
, respectively.
# We load some values, so we can test the code
a = float(input("a = "))
b = float(input("b = "))
# The solution to the problem
if a < b:
min_value = a
max_value = b
else:
min_value = b
max_value = a
# Print the result, to check if it's correct
print("a = ", a)
print("b = ", b)
print("Min:", min_value)
print("Max:", max_value)
Since Python has functions min
and max
, we can do this in a more Pythonic way:
# We load some values, so we can test the code
a = float(input("a = "))
b = float(input("b = "))
# The solution to the problem
min_value = min(a, b)
max_value = max(a, b)
# Print the result, to check if it's correct
print("a = ", a)
print("b = ", b)
print("Min:", min_value)
print("Max:", max_value)
Load a
and b
in a way that a <= b
.
This is wrong:
a = float(input("a = "))
b = float(input("b = "))
if a > b:
# a and b are in a wrong order, so we swap their values
a = b
b = a
# Print the result, to check if it's correct
print("Loaded:")
print(" a =", a)
print(" b =", b)
This is correct:
a = float(input("a = "))
b = float(input("b = "))
if a > b:
# a and b are in a wrong order, so we swap their values
tmp = a
a = b
b = tmp
# Print the result, to check if it's correct
print("Loaded:")
print(" a =", a)
print(" b =", b)
A Pythonic solution would be:
a = float(input("a = "))
b = float(input("b = "))
if a > b:
# a and b are in a wrong order, so we swap their values
(a, b) = (b, a)
# Print the result, to check if it's correct
print("Loaded:")
print(" a =", a)
print(" b =", b)
Please, do not use this until you know how and why it works.
Here is the problem:
Find the sum of a given number's digits.
While there is a very "Pythonic" way to get the digits of a number, we shall do the usual integer arithmetic algorithm that is easy to port to all major modern languages.
How do we find digits of a number x
?
The last one is easy: x % 10
is the remainder of the division $x / 10$. But what about the rest?
Here is a simple trick: once we're done with the last digit, we don't need it anymore and we can discard it. How do we do that?
Hint: we have just used the %
operator to get the last digit. Is there an operator that gives x
without the last digit?
Of course there is: operator //
(integer division) is complementary to %
. More precisely, x // 10
gives us x
without the last digit.
x = int(input())
print("x =", x)
print("x % 10 =", x % 10)
print("x // 10 =", x // 10)
A word of warning: try the above code with a negative x
!
How do we deal with this?
There is a nice function for getting the absolute value of a number, conveniently called abs()
:
x = abs(int(input()))
print("x =", x)
print("x % 10 =", x % 10)
print("x // 10 =", x // 10)
So, here is a sketch of how to solve the above problem (sum of digits):
s = 0
,x
,x
and add it to s
,x
,x
has no more digits (i.e., it drops to zero).We'll add additional print()
to the loop, to follow the states of the variables.
s = 0
x = abs(int(input()))
print("x =", x)
while x > 0:
s += x % 10
x //= 10
print("sum = " + str(s) + "; x =", x)
print("final sum =", s)
print("final x =", x)
Important: Notice the final value of x
in the last line -- it is zero. Doing the above, the value of the variable is lost and cannot be recreated!
If we need the value of x
afterwards, we have to keep it in another variable (or do the whole thing in a function, as we shall soon see):
s = 0
x = abs(int(input()))
tmp = x
print("x = " + str(x) + "; s = " + str(s) + "; tmp = " + str(tmp))
while tmp > 0:
s += tmp % 10
tmp //= 10
print("x = " + str(x) + "; s = " + str(s) + "; tmp = " + str(tmp))
print("Final values: x = " + str(x) + "; s = " + str(s) + "; tmp = " + str(tmp))
By the way, there is a shorter way to do this, but specific to Python:
print(sum(int(d) for d in str(abs(int(input())))))
We'll be able to understand the above code later on.
Whenever we write
if some_condition:
do_something()
we are effectively saying
If
some_condition
is true, thendo_something()
.
This is pretty straighforward when some_condition
has a Boolean value. However, one can use most of the types in a condition. In this case, we say that we are using those values in a Boolean context.
Some general rules of evaluation in Boolean context are:
None
and 0 (zero) evaluate to False
.
Nonzero numbers evaluate to True
.
Some examples:
x = 0
y = 1-1
if 0:
print("0 is true.")
else:
print("0 is false.")
if 17:
print("17 is true.")
else:
print("17 is false.")
if x:
print("x is true.")
else:
print("x is false.")
if y:
print("y is true.")
else:
print("y is false.")
if 1-1:
print("1-1 is true.")
else:
print("1-1 is false.")
As we learn new data structures, we will mention their Boolean interpretations as well. However, a general rule is: if the value resembles a zero or if it is empty, its Boolean interpretation is False
; otherwise, it is True
. If unsure you can easily check for yourself:
print(bool(1))