Mathematical operations are executed in an order as you get used to in mathematics.
See the precedence order of all Python operators in the documentation. Operations with the same precedence are evaluated from left to right.
E.g. 1+2*3
is evaluated as 1+(2*3)
.
Both numeric and string values can be added together.
For numeric values it works like the mathematical operation, e.g.: 1+2=3
.
For string values they are concatenated, e.g.: 'Hello '+'world'='Hello world'
.
print(1+2)
print('Hello '+'world')
x=10
y=20
print(x+y)
z='10'
q='20'
print(z+q)
Works only for numeric values:
print(10-7)
x=20
print(x-10)
The multiplication operator can be applied both between 2 numeric values and between a string and a numeric value.
For numeric values it works like the mathematical operation, e.g.: 9*4=36
.
For a string and an integer, the string is repeated and concatenated as many times as we defined, e.g.: 'Hi'*5=HiHiHiHiHi
.
print(9*4)
print('Hi'*5)
x=9
y=x*4
print(y)
z='Hi'
w=z*5
print(w)
Works only for numeric values.
print(17/3)
Question: what is the type of the dividend and the divisor? What is the type of the result?
Question: what will be the type of the result if the value is an integer?
print(type(17))
print(type(3))
print(type(17/3))
print(type(18/3))
Using the double division operator (//
) means that the result of the division will be an integer number.
If the result has a fractional part, it is dropped.
print(18//3)
print(17//3)
We can calculate the yth power of x by using the double star (*
) operator: x**y
.
print(2**3)
x=3
y=4
print(x**y)
It is effectively the same as calling the pow
function (the name is short for power) with 2 arguments:
print(pow(x, y))
In computing, the modulo operation finds the remainder after division of one number by another (called the modulus of the operation).
E.g. 17%3=2
, since 15 is divisible by 3 and the remainder is therefore 2.
Useful scenarios:
print(17%3)
Task: Calculate the area and the perimeter of a rectangle.
Get the width and the height of the rectangle from the user.
width = int(input("Width = "))
height = int(input("Height = "))
area = width * height
perimeter = 2 * (width + height)
print("Area = {0}".format(area))
print("Perimeter = {0}".format(perimeter))
Task: Calculate the area and the perimeter of a circle.
Get the radius of circle from the user.
import math
radius = float(input("Radius = "))
area = radius**2 * math.pi
perimeter = 2 * radius * math.pi
print("Area = {0}".format(area))
print("Perimeter = {0}".format(perimeter))
Note: we can get a (finite) representation of pi using the math.pi
constant after importing the math
module:
import math
print(math.pi)
There are 3 basic control flows for all imperative programming languages: sequences, conditions and loops.
When operations are evaluated seqentially one after another, it is called a sequence statement.
print("First statement")
print("Second statement")
So far, we have worked with sequences.
Conditions (or also called select statements):
First lets read a number from the user:
number = input("Give a number: ")
print("Number is {0} with type of {1}".format(number, type(number)))
Convert the number
to an integer:
number = int(number)
print("Now number is now {0} with type of {1}".format(number, type(number)))
Check whether the number is positive or not:
if number > 0:
print("number is positive, its value is " + str(number))
else:
print("number is non-positive, its value is " + str(number))
IMPORTANT: in Python, the indentation of the code is crucial, because it defines the code blocks!
if number > 0:
print("number is positive, its value is " + str(number))
else:
print("number is non-positive, its value is " + str(number))
print("Check when this line is printed")
if number > 0:
print("number is positive, its value is " + str(number))
else:
print("number is non-positive, its value is " + str(number))
print("Check when this line is printed")
Indentation is done with whitespace characters: spaces and tabs. You can either use spaces or tabs to indent and you can decide how many of them you are using. (Typical values are indenting with 2 or 4 whitespaces.)
Note: a single tab is just 1 whitespace even if displayed as multiple in your text editor! Therefore you shall not mix spaces and tabs when indenting, use only one of them!
Boolean values and expressions can also be combined with the logical, binary and
and or
operators. Negation can be done with the unary not
operator.
print("True and False is {0}".format(True and False))
print("True or False is {0}".format(True or False))
print("not True is {0}".format(not True))
Just like with the arithmetic operators, there is also a precedence order for the logical operators: not
, and
, or
.
Use parentheses to "override" the default precedence order.
print("True or True and False is {0}".format(True or True and False))
print("(True or True) and False is {0}".format((True or True) and False))
We can define multiple logical expression (elif) to test. These conditions are tested in the order they are defined and the body for the first one to be True will be executed. We can still define an else branch in case none of the conditions was True.
if number > 0:
print("number is positive, its value is " + str(number))
elif number < 0:
print("number is negative, its value is " + str(number))
else:
print("number is zero")
Actually, there are no three (or more) way conditional statements, only two-way conditions. The elif
keyword is just a little "syntax sugar" to provide an easier understandable version of nested, 2-way conditions.
Task: Can you write the above 3-way condition with just 2-way conditions?
if number > 0:
print("number is positive, its value is " + str(number))
else:
if number < 0:
print("number is negative, its value is " + str(number))
else:
print("number is zero")
You do not have to use if-else
or if-elif-...-else
. You can use if
without other clauses following that.
The else branch can be omitted if not required.
if number > 0:
print("number is positive, its value is " + str(number))
Python syntax for comparison is the same as our hand-written convention:
>
(>=
)<
(<=
)==
(Note here that there are double equal signs)!=
print(3 == 5)
print(72 >= 2)
store_name = 'Auchan'
#store_name = 'Tesco'
print(store_name)
print(store_name == "Tesco") # Will return a boolean value True or False
if store_name == 'Auchan':
print("The store is an Auchan.")
else:
print("The store is not an Auchan. It's " + store_name + ".")
IMPORTANT: Note that floating point precision and therefore comparisons between floating point numbers can be tricky.
What will these floating point mathematical operations result?
print(0.1 + 0.1 + 0.1)
print(0.1 + 0.1 + 0.1 == 0.3)
print(1.0 - 0.83)
print(1.0 - 0.83 == 0.17)
print(2.2 * 3.0)
print(2.2 * 3.0 == 6.6)
print(3.3 * 2.0)
print(3.3 * 2.0 == 6.6)
a = 1000.0
b = 0.000000001
print(a + b == a)
a = 100000000.0
b = 0.000000001
print(a + b == a)
Therefore, calculated floating point numbers shall never be checked for precise equality, instead a small error threshold shall be allowed.
a = 2.2 * 3.0
b = 6.6
print(abs(a - b) < 1e-5) # 1e-5 == 10^-5 == 0.00001 (scientific number notation)
Signed integers are usually represented with the Two's complement interpretation:
00000000 -> 0
00000001 -> 1
00000010 -> 2
00000101 -> 5
...
10000000 -> -128
10000001 -> -127
11111110 -> -2
11111111 -> -1
Floating point numbers are usually represented according to the standard IEEE-754.
Since hardware can only work with integers, numbers are represented in a form of [mantissa|exponent]
, where $value = mantissa * 2^{exponent}$.
Both mantissa and exponent are a two's complement interpretation of signed integers.
Example for converting a float representation to decimal value:
representation = [000000000101|11111100]
value = 5 * 2^-2 = 1.25
Example for converting a decimal value to float representation:
value = 179.375
binary value = 10110011.011
normal form = 0.10110011011 * 2^8
mantissa = 10110011011
exponent = 1000
representation = [010110011011|00001000]
The number base problem: not all numbers can be exactly represented in all bases. Neither 0.17 or 0.83 can be represented in base 2, so:
0.1700000000000000122124532708767219446599483489990234375 -> 0.0010101110000101000111101011100001010001111010111000011
0.8299999999999999600319711134943645447492599487304687500 -> 0.1101010001111010111000010100011110101110000101000111100
1.0 - 0.83 = 0.0010101110000101000111101011100001010001111010111000011
0.17 = 0.0010101110000101000111101011100001010001111010111000100
The floating point problem: all representations have restricted range by the exponent, performing operations on numbers with very large and small exponents could result in the ignorance of the smaller one, as it would be shifted out of range.
decimal = 100000000
binary = 101111101011110000100000000
normal = 0.101111101011110000100000000 * 2^27
decimal = 0.000000001
binary ~= 0.000000000000000000000000000001
normal ~= 0.1 * 2^-29
sum: 100000000.000000001
0.101111101011110000100000000 * 2^27 + 0.1 * 2^-29
0.101111101011110000100000000 * 2^27 + 0.000000000000000000000000000000000000000000000000000000001 * 2^27
0.101111101011110000100000000000000000000000000000000000001 * 2^27
mantissa: 101111101011110000100000000000000000000000000000000000001
If mantissa is not long enough, the last 1 bit will be shifted off.
Task: Decide whether an integer number is even or odd!
Request the number from the user.
number = int(input("Number to test: "))
if number % 2 == 0:
print("{0} is even".format(number))
else:
print("{0} is odd".format(number))
Task: Calculate the Body Mass Index (BMI) of the user and categorize it.
The BMI is defined as the body mass (in kilogramms) divided by the square of the body height (in meters), and is universally expressed in units of $kg/m^2$. $$BMI = \frac{Weight}{{Height}^2}$$
Request the weight and the height and calculate the BMI value for the user!
Categorize the user based on the BMI value:
Category | BMI value |
---|---|
Underweight | BMI < 18.5 |
Normal | 18.5 <= BMI < 25 |
Overweight | 25 <= BMI < 30 |
Obese | 30 <= BMI |
Note: this is just a simplified categorization.
weight_kg = int(input("Weight of the user (in kg): "))
height_cm = int(input("Height of the user (in cm): "))
height_m = height_cm / 100
bmi = weight_kg / (height_m**2)
print("BMI of the user is {0:.2f}".format(bmi))
if bmi < 18.5:
print("Category: underweight")
elif bmi < 25:
print("Category: normal")
elif bmi < 30:
print("Category: overweight")
else:
print("Category: obese")
Note how the conditions are tested in the order they are defined. The body of the first one to be True gets executed and the further ones are omitted.
Python code raises so called exceptions in exceptional cases, typically when an error occurred. We can use the try-except
block to handle these errors (exceptions), so our code will not stop and abort because of the error.
E.g.: lets consider we would like to request a number from the user, but the user can type in any value, even a string. Then converting this string to an integer with int()
would raise an exception. Not handling this exception will abort the program. By handling the exception we can print out an error message, set a default value or even request the number a second time.
Format:
Example without exception handling:
age = input('What is your age?')
age = int(age)
print("The given age is: {0}".format(age))
Test what will happen if you type in a string instead of a number? Will the value of the age
variable printed out?
Example with exception handling:
age = input('What is your age?')
try:
age = int(age)
except:
age = -1
print("The given age is: {0}".format(age))
Test again what will happen if you type in a string instead of a number? Will the value of the age
variable printed out?
Modify the code above by displaying an error message if not a number was given on the first attempt. Also request the age of the user a second time.
age = input('What is your age?')
try:
age = int(age)
except:
print('That was not a number, try again!')
age = input('What is your age?')
age = int(age)
print("The given age is: {0}".format(age))
Both the TRY and the EXCEPT block can contain multiple statements. Test what will happen here if you comment out the erroneous assignment of the y
variable?
x = 'Ten'
try:
print('Line 1 in TRY block')
y = int(x) # this will raise an exception
print('Line 2 in TRY block')
except:
print('Line in EXCEPT block')
print('END')
Different errors have different types which can be checked on the EXCEPT blocks.
IMPORTANT: EXCEPT blocks are tested in the order they are defined, so more specific error types MUST precede more general types.
x = 'Ten'
try:
print('Line 1 in TRY block')
y = int(x) # this will raise a ValueError
y = 10 / 0 # this will raise a ZeroDivisionError
print('Line 2 in TRY block')
except ValueError as e:
print("ValueError was raised: " + str(e))
except ZeroDivisionError:
print("ZeroDivisionError was raised")
except:
print("Unknown error was raised.")
print('END')
The try-except
structure can be extended with a finally
block. The code inside this block is always evaluated:
x = 'Ten'
try:
print('Line 1 in TRY block')
y = int(x) # this will raise a ValueError
y = 10 / 0 # this will raise a ZeroDivisionError
print('Line 2 in TRY block')
except ValueError as e:
print("ValueError was raised: " + str(e))
finally:
print('This line always gets printed')
print('END')
The finally block can be especially when some operations must be performed in all cases; e.g. an opened file must be closed even if an error occurred during its processing.
Task: Check whether a certain year is a leap year or not?
According to the Gregorian calendar, every year that is exactly divisible by 4 is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400.
Also make sure that the user input is a positive number.
try:
year = int(input('Which year to check? '))
if year > 0:
if year % 4 == 0:
if year % 100 == 0:
if year % 400 == 0:
print('{0} is a leap year'.format(year))
else:
print('{0} is NOT leap year'.format(year))
else:
print('{0} is a leap year'.format(year))
else:
print('{0} is NOT leap year'.format(year))
else:
print('That was not a positive number!')
except:
print('That was not an integer number!')
The solution can be simplified by constructing a combined condition with the logical operators and
and or
:
try:
year = int(input('Which year to check? '))
if year > 0:
if year % 400 == 0 or year % 4 == 0 and year % 100 != 0:
print('{0} is a leap year'.format(year))
else:
print('{0} is NOT leap year'.format(year))
else:
print('That was not a positive number!')
except:
print('That was not an integer number!')