1. Variables, operators and functions.#

1.1 First Python Script#

So, it is time for your first Python script. It is located beneath.

# My First Python Script
message = 'Hello world!'
print(message)
Hello world!

Let’s break it down

First line: # My First Python Script is a comment, which is used just to explain and/or put useful information about the code next to it. If you need to create a comment — just type a # symbol and write your text after it. The interpreter does nothing with it — the comments are there just as useful information for you or another reader.

Second line: message = ‘Hello world!’ creates a variable called message and assigns the text literal (string) Hello world! to it, by using the operator = (equal sign). Variables are used to store all data you use in your code.

Third line: print(message) calls the functionprint() and passes the variable message to it. A function is just a set of encapsulated code, which is tailored to perform a certain action. This specific function outputs the content of everything you pass to it. Since the variable message had a small line of text in it, the function print() outputs that message.

This script is quite primitive and simple but it represents the main idea of programming in Python. You have data (which is stored in variables) and you perform an operation on it: by using the inbuilt print() function. In addition, you could create your own functions.

1.2 Python Variables#

One of the most powerful features of a programming language is the ability to create and manipulate variables. A variable is a labeled storage that refers to a value. They are usually used in a way to make the code more readable, allowing reusability of your code.

As it was mentioned previously, Python is a high-level programming language. For that, it uses concepts of Class and Object. In short, a Class is a defined model or a data structure, it describes how the data of that class can be described and how it can be manipulated, and an Object or Instance is its realization. In other words, think about your favorite meal: the recipe is the Class of your meal and when you decide to use the recipe and cook it — you create an Object of that Class. Variables are the way how objects are stored and processed.

Rules for variable names#

  • names can not start with a number

  • names can not contain spaces, use _ instead

  • names can not contain any of these symbols:

    :'",<>/?|\!@#%^&*~-+
    

::: {note}

  • it’s considered best practice (PEP8) that names are lowercase with underscores

  • avoid using Python built-in keywords like list and str :::

Assigning Variables#

Variable assignment follows variable_name = value, where a single equal sign $=$ is an assignment operator. More on operators will be covered in the next section. Let’s see a few examples of how we can do this.

Let’s create an object called a and assign it the number 5

a = 5

Now if I call a in my Python script, Python will treat it as the number $5$.

Adding the objects

a + a
10

What happens on reassignment? Will Python let us write over it?

a = 20

Check

print(a)
20

Yes! Python allows you to overwrite assigned variable names. We can also use the variables themselves when doing the reassignment.

Since a = 20 was the last assignment to our variable a, you can keep using a in place of the number 20:

a + a
40

Instead of writing a+a, Python has a built-in shortcut for these simple operations.

You can add, subtract, multiply and divide numbers with reassignment using +=, -=, *=, and /=, respectively.

a += 10

The above code will add 10 to the variable a every time you run that cell.

Try it yourself, run it a few times and then run the below cell to see what’s the value of a .

print(a)
30

Below an example of a code that will double a every time that you run that cell.

a *= 2
print(a)
60

Determining variable type with type()#

You can check what type of object is assigned to a variable using Python’s built-in type() function. Common data types include:

  • int (for integer numbers)

  • float (for floating point / all real numbers)

  • str (for string/text)

  • bool (for Boolean True/False)

  • list

  • tuple

  • dict

  • set

::: {warning} Always check the type of your variables when debugging! :::

Below a few examples:

type(a)
int
float_var = 3.1415
type(float_var)
float
a = 0.3
b = 0.2
c = a-b
print(c)
0.09999999999999998

You probably noticed that Python wrote $0.09999999999999998$ instead of $1$ when calculating $0.3 - 0.2$. Ignore it for now, this is explained later in this Notebook.

type(1<2)
bool

Boolean variables can only take on two values: True or False. They are often used to check conditions.

1<2
True

The variable from the first script

type(message)
str

Strings are variables represented in between ’ ‘ or ” “.

They are a sequence of values, therefore you are able to access and manipulate every character individually.

This is done with the bracket operator [], which works as an index.

Let’s take a look at our first variable from this notebook: message.

message
'Hello world!'
message[1]
'e'

Nani???

Why index [1] gave us the second letter? For most people, the first letter of the sentence Hello world! is H not e.

So.. what happened?

In Python, indexing starts at [0]. H is the zero-th character of Hello world!.

message[0]
'H'

You can also access the last value of a string using the index [-1], the before-last using [-2] and so forth.. This will turn out to be very useful!

message[-1]
'!'

Strings are also immutable. You cannot reassign a new value for one of the characters. You will have to create a new string for that.

message[0] = 'J'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[20], line 1
----> 1 message[0] = 'J'

TypeError: 'str' object does not support item assignment

You can also add (i.e. concatenate) strings and characters. But it will create a new string, it will not modify the old one (since they are immutable).

message + message
'Hello world!Hello world!'
message[0]+message[1]+message[2]+message[3]
'Hell'

A segment of a string is called a slice. Selecting a slice is similar to selecting a character. Using the operator : you select the first value that you want to get, and the first value you want to leave out of the slice, for example:

Let’s say we want to write the word Hell using our variable message, without having to type as much as above.

  1. Which letter is the first we want to get? H, which has index [0].

  2. Which letter is the first we want to leave out? o, which has index [4]. So…

message[0:4]
'Hell'

One can also use our variable message to write the sentence Hold door.

message[0]+message[4]+message[-3:-1]+message[5]+message[-2]+2*message[4]+message[-4]
'Hold door'

::: {note} Real life example: Analyzing satellite data

Sentinel data title is formatted as: S1A_IW_SLC__1SDV_20181205T015821_20181205T015851_024884_02BD8C_8700
where each part means something, S1A means Sentinel-1A, IW means Interferometric Wide Swath
20181205T015821 is a date, 2018 12 05, at 01h58m21s, etc.

Therefore, being able to manipulate this string is fundamental in order to organize and select satellite data. :::

Dynamic Typing#

The way the computer is able to use the stored data becomes an attribute of the stored data. This attribute is called a data type. Python uses dynamic typing, meaning you can also reassign variables to different data types. This makes Python very flexible in assigning data types; it differs from other languages that are statically typed.

Pros and Cons of Dynamic Typing#

Pros of Dynamic Typing#
  • very easy to work with

  • faster development time

Cons of Dynamic Typing#
  • may result in unexpected bugs!

  • you need to be aware of type().

a = 5
print('Type of a is =',type(a))
a = 'string'
print('Type of a is =',type(a))
Type of a is = <class 'int'>
Type of a is = <class 'str'>

See, now a is no longer an int type but a str type

Casting types#

Sometimes you want to change the type of a variable. For example, there is no point in arithmetically adding a number to a string. Or, when estimating the amount of oil wells, those should be integers (how would you build $2.5$ wells?). These two problems can be sometimes solved with casting.

Casting is a procedure of changing variables type. Actually, you create a new variable with the requested data type using the variable you want to alter.

Examples are shown below.

string_number = '123'
print(string_number, type(string_number))

integer_number = int(string_number)
print(integer_number, type(integer_number))
123 <class 'str'>
123 <class 'int'>

As you can see, both variables look the same in the output but their type now is different. Because of that, the cell below will result in an error.

string_number + 5
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[28], line 1
----> 1 string_number + 5

TypeError: can only concatenate str (not "int") to str

But the next cell will run normally.

integer_number + 5
128

How do computers read variables?#

Computers and humans have different views on data. We, fellow humans, can easily read poetry and enjoy music. Computers are limited in that sense and they can operate on a really primitive level. They cannot even read normal text, for a computer, everything is represented with numbers. One of the popular text encodings ASCII has a table, where every symbol there is an integer number assigned to it. Letter ‘a’, for instance, has a value of $97$, and letter ‘A’ has a value of $65$. The value of ‘B’ is $66$ and if we want to take the letter before ‘B’ we just calculate $66 - 1$. You don’t have to open an alphabet and, therefore, it is easier to work with numbers than with letters.

But even for numbers, computers have their own approach. On a really low level, all numbers are stored and operated in their binary form. Number $5$ becomes $101$, because $5 = 1\cdot2^2 + 0 \cdot2^1 + 1\cdot2^0$. And since all symbols are also represented with numbers, it is not hard for computers to operate with them. But what about the floating numbers? How do you represent $1.5$ or $\pi$? Well, computers try to represent them with binary code, which introduces some problems. In order to represent a fraction, they need an infinite amount of bits, to obtain the precision we use in math. But that’s impossible! In other words, small errors will always be present in calculations as simple as $0.3 - 0.2$. From your math classes you know that the result of $0.3 - 0.2 = 0.1$, not $0.10001$ or $0.09999$. But try to run the cell below and see the result.

0.3 - 0.1
0.19999999999999998

It is not what you would expect to see, right? The result has an error of $\approx 10^{-15}$. In most cases, it can be neglected but be careful when comparing float and int numbers, as shown below.

0.2 == 0.3-0.1
False

Indeed, $0.2 \neq 0.19999999999999998$.

::: {note} Within this course, in the end of each section you’ll find exercises related to the subject that was just covered. There are three types of exercises: normal, fixing and searching.

Normal exercises are straight forward exercises that you should be able to solve without much trouble. Fixing exercises are exercises where some piece of code is already written and you need to debug it (find the root of the error and fix it).

Searching exercises are exercises that purposefully incorporate subjects that were not covered yet, in an attempt to encourage you to try and solve issues you haven’t learned about yet. :::

1.3 Python Operators#

Python operators are used to perform operations on variables and values. They are symbols that represent a form of computation; think of addition or multiplication. The value to which this computation is applied to is called the ’operand’. Most of the common operators you will recognize from mathematics.

Arithmetic Operators

Math sign

Python sign

name

+

+

addition

-

-

subtraction

*

*

multiplication

/

/

division

^

**

exponentiation

mod

%

modulus

//

floor division


Most of the mathematical symbols stay the same when transforming a piece of mathematics to Python. Note that the exponentiation sign is a double multiplication sign!

The last two operators, modulus and floor division, can be defined as the following:

  • modulus: return the remainder of a division

  • floor division: returns the integer/whole part of the division

Now we will provide some small examples

a. multiply 4 by 3 and then add 2

b. 2 to the power of 4 plus 1

c. take the modulus of 352 over 23

d. the floor division of 352 over 23

a = 2 + 4 * 3
print(a)
14
b = 2**4 + 1
print(b)
17
c = 352 % 23
print(c)
7

Explanation: $352 = 15 \times 23 + 7$, therefore the modulus operator returns the value $7$.

d = 352 // 23
print(d)
15

Explanation: $352 = 15 \times 23 + 7$, therefore the floor division operator returns the value $15$.

Besides making sure that you use the right operators when writing mathematical functions, it is also important that you pay attention to the order of operators. When not done right, this can cause huge changes in the outcome. Therefore, when writing out large equations it is easier to use parentheses or split it into multiple variables. e.g.:

$$y = x\tan\theta - \frac{1}{2v_0^2}\frac{g x^2}{\cos^2\theta} + y_0$$

You could split this equation into four distinct variables:

  1. var_1 $ = x\tan\theta$

  2. var_2 $= \frac{1}{2v_0^2}$

  3. var_3 $= \frac{g x^2}{\cos^2\theta}$

  4. var_4 $= y_0$

And then re-write it as y = var_1 - (var_2 * var_3) + var_4

parenthesis_before = (2 + 4) * 3
print('With parenthesis before =',parenthesis_before)
parenthesis_after = 2 + (4 * 3)
print('With parenthesis after =',parenthesis_after)
With parenthesis before = 18
With parenthesis after = 14

Comparison Operators#

In Python, you often want to compare a value with another. For that, you use comparison operators.

Math sign

Python sign

Meaning

$=$

==

Equal to

$>$

>

Greater than

$>$

<

Less than

$\geqslant$

>=

Greater than or equal to

$\leqslant$

<=

Less than or equal to

$\neq$

!=

Not equal to

Checking if a value corresponds to the set conditions#

Check if the the variable num satisfies the set condition.

num = 6
print(num > 2)
True

If the value does not satisfy the condition the system will return False

print(num > 7)
False

Logical & Identity Operators#

sign

description

and

returns True if both statements are true

or

return True if at least 1 statements is true

not

reverse of the results; returns False if the statement is True

is

returns True if both variables are the same object

is not

returns True if both variables are not the same object

in

returns True if a sequence with the specified value is present in the object

in not

returns True if a sequence with the specified value is not present in the object

and statement#

By using the and statement you can set multiple conditions for the system to return. This can be seen as setting a boundary condition for a mathematical function.

num = 5
print(num > 4 and num < 8)
True

checking if a value appears in an object#

Suppose we have a string “sandstone”, we can check if a value is present within the string through the following lines of code.

rock_type = "sandstone"
print("sand" in rock_type)

is and == operators#

The is operator deserves a little more explanation since it can be easily confused with the == operator. The is statement does not compare the value of a variable but simply checks if two variables are the same object. On the other hand, == checks if the values of different variables are the same. In the underneath piece of code this is shown quite clearly. Although the values of the variables are the same, their type is not. Therefore, when compared using the is operator, it returns False.

x = 2.0
y = 2

print(type(x),type(y),x is y)
print(x == y)
<class 'float'> <class 'int'> False
True

1.4 Python Functions#

A function is a collection of code that is assigned to a specific name. You have already seen some built-in Python functions, such as print(). Using functions is useful because it allows you to run the same code again without having to type it a second time.

Below are some examples of common built-in Python functions and what they do:

  • print(): Prints input to screen

  • type(): Returns the type of the input

  • abs(): Returns the absolute value of the input

  • min(): Returns the minimum value of the input. (input could be a list, tuple, etc.)

  • max(): Same as above, but returns the maximum value

  • sum(): Returns the sum of the input (input could be a list, tuple, etc.)

But the story doesn’t end at built-in functions. You can also write your own functions!

How to write a function#

To write a function, you must first define it. This is done by using the def statement. Then, you name the function and add, in the parentheses, which variables this function takes as an input, followed by a colon. The colon tells Python you are going to define the function body next (the part of the function that actually does the computation). As shown below:

def function_name(input1, input2,...):
function_body
...
...

The calculate_circle_area(r) function below defines pi as a variable and then computes the area of a circle, which is stored in the variable area. Finally, it uses the return statement to output the area back to you. Once you have defined the function, you can then call it by typing the function name, and the inputs in the parenthesis. For example, calling: print(“Hello World!”), prints the string ”Hello World!”.

Indentation

It is worth noting that the function body should be indented. This is how Python sees what piece of code is inside another code. An indented line of code is a line that starts with whitespace. You can do this by using the tab key on your keyboard.

::: {note} Inputs of functions are more often called arguments. :::

indentation of code within functions#

Let’s say you’d want to compute the area of a circle, but you don’t want to calculate $\pi r^2$ the entire time. Then you can write a couple lines of code to do it for you, and wrap it up into a function, like the one below:

def calculate_circle_area(r):
    pi = 3.141592653589793
    area = pi*(r**2)
    return area

This function is called calculate_circle_area(r), and takes the value r as an argument.

Functions can have multiple arguments, for example:

def calculate_rectangle_area(a, b):
    area = a * b
    return area

print('Area of my rectangle is', calculate_rectangle_area(4, 6), 'cm^2')
Area of my rectangle is 24 cm^2

In the cell above, the calculate_rectangle_area(a, b) function takes $2$ arguments, $a$ and $b$.

The built-in function print() takes $3$ arguments:
the string ’Area of my rectangle is’, the output of calculate_rectangle_area(a, b), and another string ’cm^2’.

There are better ways to use the built-in print() function when writing long sentences that have variables in between. For example:

print('Area of my rectangle is {} cm^2 and the area of my circle is {} cm^2'. \
      format(calculate_rectangle_area(4,6), calculate_circle_area(4)))
Area of my rectangle is 24 cm^2 and the area of my circle is 50.26548245743669 cm^2

If a line in your code extends the width of your page, you can use a \ at the point where you want to break the line, as shown above.

Note that the variables (separated by commas) called inside the .format() will appear, in order, where the { } are located.

Furthermore, you can also format how you want the numbers to appear, as shown below:

print('Area of my rectangle is {:.5f} cm^2 and the area of my circle is {:.2f} cm^2'. \
      format(calculate_rectangle_area(4,6), calculate_circle_area(4)))
Area of my rectangle is 24.00000 cm^2 and the area of my circle is 50.27 cm^2

Where the :.5f states that you want to print that variable with $5$ decimal numbers. Similarly, :.2f rounds the number to $2$ decimal numbers. More information on this in Section 3.1, in Notebook 3.

Documenting functions#

We have now successfully created a function that computes the area of a circle and the area of a rectangle. You could send this code to fellow students, but maybe they wouldn’t know how to use them. This is where a docstring comes in handy. This is a string specified in the beginning of the function body which states information about the function. A lot of built-in Python functions also have docstrings, which is really useful when you’re trying to understand how to use a function.

Add a description to the calculate_circle_area(r) function below, as a docstring.

def calculate_circle_area(r):
    '''This function calculate the area of a circle with radius r '''
    pi_circle = 3.141592653589793
    area = pi_circle*(r**2)
    return area

As you can see, nothing happened. But, if we now call the function like this:

calculate_circle_area?

or:

help(calculate_circle_area)

we should see the description (docstring) of the function. Try yourself below:

help(calculate_circle_area)
Help on function calculate_circle_area in module __main__:

calculate_circle_area(r)
    This function calculate the area of a circle with radius r

Now this isn’t of much use when you work on your own code, unless you are very forgetful or have to write large programs. But if you work using other people’s code, this is really useful, as it helps you figure out how to use each function.

When to write or use a function?#

You can use functions in your code when you have a specific piece of code that you need to use multiple times (e.g.: plotting something).

Often you will find you want to use an output from a function later on. To do this, you can assign a function to a variable. Let’s say I want to use the area of a circle in a later calculation. Then you can store it in a variable like this:

We stored the area of a circle that has a radius 4 in the variable Circle_Area

Circle_Area = calculate_circle_area(4)

Nothing happens, but the value of calculate_circle_area(4) is now stored in the variable Circle_Area. See below:

print(Circle_Area)
50.26548245743669

We can see that the value was indeed stored.

::: {warning} Variables that are defined inside a function body can NOT be called from outside of the function. These variables are called local variables. :::

Take the variable pi_circle that we defined in the function calculate_circle_area(). If we try to print it:

print(pi_circle)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[52], line 1
----> 1 print(pi_circle)

NameError: name 'pi_circle' is not defined

See, it doesn’t work! The error you get: NameError: name ‘pi_circle’ is not defined, means that you tried to call a variable that does not exist.

Additional study material:#

  • Official Python Documentation - https://docs.python.org/3/tutorial/introduction.html

  • https://realpython.com/python-variables/

  • Think Python (2nd ed.) - Section 2

  • Official Python Documentation - https://docs.python.org/3/library/operator.html

  • https://realpython.com/python-operators-expressions/

  • Think Python (2nd ed.) - Sections 2 and 5

  • Official Python Documentation - https://docs.python.org/3/tutorial/controlflow.html#defining-functions

  • https://realpython.com/defining-your-own-python-function/

  • Think Python (2nd ed.) - Sections 3, 6 and 16

After this Notebook you should be able to:#

  • understand why you need to learn Python

  • create and re-assign new variables

  • determine the type of a variable using type()

  • slice strings

  • perform simple math using arithmetic operators

  • compare two or more variables

  • check if a value, or element, exists in an object

  • define a function, including its docstring