print("Hello, World!")
Hello, World!
This exercises serves as a basic introduction to Python for Scientific Computing.
As with any language, you must speak it to learn it. This holds true for Python as well. In the following, we will cover the basics of Python to get us started 1. But expect to keep learning ways to express your ideas in Python.
This text is written in a computer file called Jupyter Notebook, typically with the extension .ipynb
. Jupyter is an interactive platform where you can write code and text and make visualizations. To run the notebook, i.e., to execute the Python code inside, you need to connect the notebook to a so-called Python kernel or runtime. There are two options: you run the kernel locally on your computer or in the cloud on the internet.
The easiest way to run a Jupyter Notebook is to use Google Colab, which requires a Google account. The advantage is that you don’t need to worry about installing anything on your machine — other notable cloud options include binder, which is, however, more cumbersome to set up. At Uni Bonn, there is also the option to launch a Jupyter lab via ecampus.
The alternative to an internet-based execution of the Python code inside a Jupyter Notebook is to install Python locally on your machine. I recommend doing so. If you are new to Python, we recommend downloading the Anaconda installer and following the installation instructions. Once installed, we’ll use the Jupyter Notebook or Jupyter Lab interface to write code.
Execute the following code cell:
print("Hello, World!")
Hello, World!
Note that within a Jupyter Notebook, you don’t need the print
function if you simply want to see the output of a cell’s last line.
"Hello Jupyter"
'Hello Jupyter'
The print
function is useful for viewing the output of multiple lines.
print("Hello Alice?")
print("Hello Bob")
Hello Alice?
Hello Bob
"Hello Alice?"
"Hello Bob"
'Hello Bob'
A convenient way to get help on almost anything in Python is to add a ?
behind the Python object. Try it with the print
function in the cell below.
# ...
Also, be not afraid of Python errors. They often give you handy tips on how to resolve a problem.
Pro tip. Familiarize yourself with the keyboard shortcuts for a more convenient notebook experience, e.g., execute a code cell and advance by pressing Shift+Enter
, use a
for inserting a code cell above, b
for below, dd
for deleting a cell, z
for undoing your last move, Enter
for entering into a cell, Esc
for leaving a cell, m
for changing a cell to a Markdown cell, and y
for changing it back to a code cell.
Everything in Python is an object. Every number, string, data structure, function, class, module, etc., exists in the Python interpreter as a Python object. An object may have attributes and methods associated with it. For example, let us define a variable that stores an string:
= "Alice" var
A convenient way to see which methods and attributes are associated with an object is to use tab completion. Write var.
and press TAB in the cell below.
# ...
Transform the text in the variable var
to uppercase. Use tab-completion to find the appropriate method.
# ...
A variable is created as soon as a value is assigned to it. We don’t have to define the type of the variable explicitly, as we do in other programming languages, because Python can automatically guess the type of data entered (dynamically typed). For example,
= 5
x = 3.14
y = "Alice"
name = True is_student
You can assign values to several variables simultaneously by using commas to separate the variable names and their corresponding values.
= "red", "green", "blue" color1, color2, color3
You can assign the same value to several variables by chaining multiple assignment operations in one statement.
= color5 = color6 = "magenta" color4
Any data or information stored within a Python variable has a type.
View the data type stored within each variable form above using the type
function.
# ...
Variable names can be short (a
, x
, y
, etc.) or descriptive (my_favorite_color
, profit_margin
, the_3_musketeers
, etc.). However, I recommend using descriptive variable names to make it easier to understand the code.
The rules below must be followed while naming Python variables: * A variable’s name must start with a letter or the underscore character _
. It cannot begin with a number. * A variable name can only contain lowercase (small) or uppercase (capital) letters, digits, or underscores (a-z
, A-Z
, 0-9
, and _
). * Variable names are case-sensitive, i.e., a_variable
, A_Variable
, and A_VARIABLE
are all different variables.
Python employs a mechanism called Call by Object Reference. When an object is assigned to a variable name, the variable acts as a reference to that object. For instance, consider the following assignment:
= [5, 3] x
Here, the variable name x
points to the memory location of the object [5, 3]
. Now, if we assign x
to a new variable y
:
= x y
In this case, the variable y
now also points to the same object [5, 3]
. This means the object [5, 3]
is not duplicated in a different memory location for y
. To illustrate this, let’s add an element to y
:
4)
y.append( y
[5, 3, 4]
x
[5, 3, 4]
When we modified y
, it is important to note that x
also updated to the same object. This demonstrates that x
and y
refer to the same object rather than independent copies.
Python includes fundamental arithmetic operations by default. Below are a few examples. Specifically, the **
operator is used for exponentiation.
= 12
a = 2
b
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a ** b)
print(a % b) # modulo operator
14
10
24
6.0
144
0
Python includes various built-in containers or data structures 2 for data storage.
A list is a sequence of Python objects with two key characteristics
Lists can be defined as a sequence of Python objects separated by commas and enclosed in square brackets []
. For example, below is a list consisting of three integers.
= [4,7,3,5,7,1,5,87,5] list_example
We can check the data type of a Python object using the in-built function type()
. Let us check the data type of the object list_example
.
type(list_example)
list
Indexing means accessing the elements of a list by their respective position. Indexing in lists includes both
For example,
0] list_example[
4
-1] list_example[
5
List slicing is a technique in Python that allows you to extract a portion of a list by specifying a range of indices. It creates a new list containing the elements from the original list within that specified range. List slicing uses the colon :
operator to indicate the start
, stop
, and step
values for the slice. The general syntax is:
new_list = original_list[start:stop:step]
Here’s what each part of the slice means:
start
: The index at which the slice begins (inclusive). If omitted, it starts from the beginning (index 0).stop
: The index at which the slice ends (exclusive). If omitted, it goes until the end of the list.step
: The interval between elements in the slice. If omitted, it defaults to 1.Exercise 🚧. Try it out.
# ...
For removing an element from the list, the pop
and remove
methods may be used. The pop
method removes an element at a particular index, while the remove
method removes the element’s first occurrence in the list by its value.
Exercise 🚧. Try it out.
# ...
List comprehensions offer a clear and concise method to generate new lists by applying an expression to each element in an iterable (such as a list or range) and can filter items based on a specified condition. The fundamental syntax for a list comprehension is as follows:
new_list = [expression for item in iterable if condition]
expression
: This is the expression that is applied to each item in the iterable. It defines what will be included in the new list.item
: This is a variable that represents each element in the iterable as the comprehension iterates through it.iterable
: This is the source from which the elements are taken. It can be any iterable, such as a list, range, or other iterable objects.condition
(optional): This filter can be applied to control which items from the iterable are included in the new list. If omitted, all items from the iterable are included.For example, to create a list of even numbers from 1 to 20, we can write
for x in range(1, 21) if x % 2 == 0] [x
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
Exercise 🚧. Use a list comprehension to create a list that has squares of natural numbers from 5 to 15.
# ...
A tuple is a sequence of Python objects with two key characteristics:
A tuple can be defined as a sequence of Python objects separated by commas and enclosed in rounded brackets ()
. For example, below is a tuple containing three integers.
= (2,7,4) tuple_example
We can check the data type of a Python object using the in-built function type()
. Let us check the data type of the object tuple_example
.
type(tuple_example)
tuple
Tupe indexing is identical to list indexing.
Tuples can be concatenated using the +
operator to produce a longer tuple:
2,7,4) + ("another", "tuple") + ("mixed","datatypes",5) (
(2, 7, 4, 'another', 'tuple', 'mixed', 'datatypes', 5)
If tuples are assigned to an expression containing multiple variables, the tuple will be unpacked, and each variable will be assigned a value in the order in which it appears. See the example below.
= (4.5, "this is a string", (("Nested tuple",5)))
x,y,z print(x)
print(y)
print(z)
4.5
this is a string
('Nested tuple', 5)
Unlike lists and tuples, a dictionary is an unordered collection of items. Each item stored in a dictionary has a key and value. You can use a key to retrieve the corresponding value from the dictionary. Dictionaries have the type dict
.
Dictionaries are created by enclosing key-value pairs within braces or curly brackets {
and }
, colons to separate keys and values, and commas to separate dictionary elements.
The dictionary keys and values are Python objects. While values can be any Python object, keys need to be immutable Python objects, like strings, integers, tuples, etc. Thus, a list can be a value, but not a key, as elements of a list can be changed.
= {'USA':'Joe Biden', 'India':'Narendra Modi', 'China':'Xi Jinping'} dict_example
Elements of a dictionary can be retrieved by using the corresponding key.
'India'] dict_example[
'Narendra Modi'
dict_example.keys()
dict_keys(['USA', 'India', 'China'])
dict_example.values()
dict_values(['Joe Biden', 'Narendra Modi', 'Xi Jinping'])
dict_example.items()
dict_items([('USA', 'Joe Biden'), ('India', 'Narendra Modi'), ('China', 'Xi Jinping')])
New elements can be added to a dictionary by defining a key in square brackets and assigning it to a value:
'Japan'] = 'Fumio Kishida'
dict_example['Countries'] = 4
dict_example[ dict_example
{'USA': 'Joe Biden',
'India': 'Narendra Modi',
'China': 'Xi Jinping',
'Japan': 'Fumio Kishida',
'Countries': 4}
Elements can be removed from the dictionary using the del
method or the pop
method:
del dict_example['Countries']
dict_example
{'USA': 'Joe Biden',
'India': 'Narendra Modi',
'China': 'Xi Jinping',
'Japan': 'Fumio Kishida'}
'USA') dict_example.pop(
'Joe Biden'
dict_example
{'India': 'Narendra Modi', 'China': 'Xi Jinping', 'Japan': 'Fumio Kishida'}
New elements can be added, and values of existing keys can be changed using the update
method:
= {'USA':'Joe Biden', 'India':'Narendra Modi', 'China':'Xi Jinping','Countries':3}
dict_example dict_example
{'USA': 'Joe Biden',
'India': 'Narendra Modi',
'China': 'Xi Jinping',
'Countries': 3}
'Countries': dict_example['Countries']+1, 'Japan':'Fumio Kishida'})
dict_example.update({ dict_example
{'USA': 'Joe Biden',
'India': 'Narendra Modi',
'China': 'Xi Jinping',
'Countries': 4,
'Japan': 'Fumio Kishida'}
If a piece of code or an algorithm is utilized multiple times within a program, it can be defined separately as a function. Doing so improves both the code structure and clarity.
To create a new function, use the def
keyword. For instance,
def greet(name):
return f"Hello, {name}!"
Here, name
is called an argument or parameter of the function.
Indentation: Python heavily utilizes indentation (white space preceding a statement) to establish code structure. This feature enhances readability and comprehension of Python code. Improper indentation can lead to issues. To indent your code, position the cursor at the beginning of the line and press the Tab
key once. Pressing Tab
again will create an additional indent, while Shift+Tab
will decrease the indentation by one level.
"Alice") greet(
'Hello, Alice!'
"Bob") greet(
'Hello, Bob!'
When defining functions, understanding variable scope is crucial.
Local Variable. Variables declared within a function have a local scope, meaning they can only be accessed inside that function. These are referred to as local variables.
Global Variable. Conversely, a variable declared outside of any function is called a global variable. This means a global variable can be accessed both inside and outside the function.
Calling a function with numerous arguments can be confusing and lead to mistakes. Python allows the use of named arguments for improved clarity. Additionally, you have the option to distribute the function call across several lines.
def create_profile(first_name, last_name,
=None, email=None, phone=None, address=None, city=None, state=None, zip_code=None,
age="Germany"):
country"""
Creates a user profile with the given information. Some fields have default values.
"""
print(f"First Name: {first_name}")
print(f"Last Name: {last_name}")
print(f"Age: {age}")
print(f"Email: {email}")
print(f"Phone: {phone}")
print(f"Address: {address}")
print(f"City: {city}")
print(f"State: {state}")
print(f"Zip Code: {zip_code}")
print(f"Country: {country}")
Here, all arguments except for the first two are optional. You can invoke the function with or without these arguments; if no arguments are provided, the default value will be applied. Functions that include optional arguments provide greater flexibility in their usage.
= create_profile(
user_profile "Jane",
="Doe",
last_name="jane.doe@example.com",
email="Bonn") city
First Name: Jane
Last Name: Doe
Age: None
Email: jane.doe@example.com
Phone: None
Address: None
City: Bonn
State: None
Zip Code: None
Country: Germany
Using special symbols, we can pass a variable number of arguments to a function. There are two special symbols:
*args
(Non-Keyword Arguments)*kwargs
(Keyword Arguments)def myFun(name, *args, **kwargs):
print("Name:", name)
print("args: ", args)
print("kwargs: ", kwargs)
Now we can use both *args
and **kwargs
to pass arguments to this function
'John',22,'cs',city="Bonn",age=22,major="cs") myFun(
Name: John
args: (22, 'cs')
kwargs: {'city': 'Bonn', 'age': 22, 'major': 'cs'}
Similar to other programming languages, Python includes built-in keywords that facilitate conditional control flows in code.
One of the most powerful features of programming languages is branching, which enables making decisions and running alternative statements depending on whether specific conditions are true. In Python, we can use the if
, else
, and elif
(short for else if) keywords. For example,
def what_is_x(x):
if x > 0:
print("x is positive")
elif x > -10:
print("x is negative")
else:
print("x is below -10")
=-9) what_is_x(x
x is negative
Another powerful feature of programming languages, closely associated with branching, is the ability to repeatedly execute one or more statements. This capability is commonly known as iteration or looping. There are two primary methods to achieve this in Python: for
loops and while
loops.
A for
loop is used for iterating or looping over sequences, i.e., lists, tuples, dictionaries, strings, and ranges. For example,
= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
days
for day in days:
print(day)
Monday
Tuesday
Wednesday
Thursday
Friday
The range
function is used to create a sequence of numbers that can be iterated over using a for
loop. It can be used in 3 ways:
range(n)
- Creates a sequence of numbers from 0
to n-1
range(a, b)
- Creates a sequence of numbers from a
to b-1
range(a, b, step)
- Creates a sequence of numbers from a
to b-1
with increments of stepExercise 🚧. Try it out.
# ...
Ranges are used for iterating over lists when you need to track the index of elements while iterating.
= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']
a_list
for i in range(len(a_list)):
print('The value at position {} is {}.'.format(i, a_list[i]))
The value at position 0 is Monday.
The value at position 1 is Tuesday.
The value at position 2 is Wednesday.
The value at position 3 is Thursday.
The value at position 4 is Friday.
Here, the format
method of the string inserts its arguments at the positions where the {}
s serve as a placeholder.
Another way to achieve the same result is by using the enumerate
function with a_list
as an input, which returns a tuple containing the index and the corresponding element.
for i, val in enumerate(a_list):
print('The value at position {} is {}.'.format(i, val))
The value at position 0 is Monday.
The value at position 1 is Tuesday.
The value at position 2 is Wednesday.
The value at position 3 is Thursday.
The value at position 4 is Friday.
A while
loop executes a block of code for as long as a condition is true. For example, let’s try to calculate the factorial of 100 using a while loop. The factorial of a number n
is the product (multiplication) of all the numbers from 1
to n
, i.e., 1*2*3*...*(n-2)*(n-1)*n
.
= 1; i = 1 # We can define multiple variables in one line by separating them with a ;
result
while i <= 100:
= result * i
result = i+1
i
'The factorial of 100 is: {}'.format(result)
'The factorial of 100 is: 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000'
Be aware of infinite loops. Suppose the condition in a while loop always holds true. In that case, Python repeatedly executes the code within the loop forever, and the execution of the code never completes. This situation is called an infinite loop. It generally indicates that you’ve made a mistake in your code. For example, you may have provided the wrong condition or forgotten to update a variable within the loop, eventually falsifying the condition.
If your code is stuck in an infinite loop during execution, just press the “Stop” button on the toolbar (next to “Run”) or select “Kernel > Interrupt” from the menu bar. This will interrupt the execution of the code. The following two cells both lead to infinite loops and must be interrupted.
DeepDive | break
and continue
statement
These statements alter the flow of a loop.
We can use the break
statement within the loop’s body to immediately stop the execution and break out of the loop.
= 1
i = 1
result
while i <= 100:
*= i
result if i == 42:
print('Magic number 42 reached! Stopping execution..')
break
+= 1
i
print('i:', i)
print('result:', result)
Magic number 42 reached! Stopping execution..
i: 42
result: 1405006117752879898543142606244511569936384000000000
With the continue
statement, we break out of the current iteration and continue to the next one.
= 1
i = 1
result
while i <= 10:
+= 1
i if i % 2 == 0:
print('Skipping {}'.format(i))
continue
print('Multiplying with {}'.format(i))
= result * i
result
print('i:', i)
print('result:', result)
Skipping 2
Multiplying with 3
Skipping 4
Multiplying with 5
Skipping 6
Multiplying with 7
Skipping 8
Multiplying with 9
Skipping 10
Multiplying with 11
i: 11
result: 10395
There are several built-in functions in Python like print()
, abs()
, max()
, sum()
etc., which do not require importing any library. We can extend these functions by importing external libraries. Here, we will cover some popular libraries for basic scientific computing.
NumPy is a fundamental library for numerical computing in Python. It provides support for arrays, matrices, and mathematical functions, making it essential for scientific and data analysis tasks. It is mostly used for performing numerical operations and efficiently storing numerical data.
import numpy as np
= np.array([1, 2, 3])
vector = np.array([[3, 1],
matrix 0, 2]])
[print(vector)
print(matrix)
[1 2 3]
[[3 1]
[0 2]]
SciPy is used for performing scientific computing such as solving differential equations, optimization, statistical tests, etc. In particular, its eigenvalue computation method seems to be more stable than NumPy’s.
import scipy as sp
Use the scipy.linalg
module to calculate the eigenvalues and eigenvectors of the matrix
defined above. If you need to refresh your knowledge about eigenvectors and eigenvalues, I recommend watching this video by 3Blue1Brown. Use your knowledge from above on how to get help inside a Python Jupyter Notebook.
# ...
Matplotlib is a comprehensive library for creating static, animated, or interactive plots and visualizations. It is commonly used for data visualization and exploration.
import matplotlib.pyplot as plt
For example, we can create a scatter plot of 1000 random sample, generate from the numpy.random
module.
42) # The seed makes the result reproducible
np.random.seed(1000), np.random.randn(1000)); plt.scatter(np.random.randn(
SymPy is a Python library for symbolic mathematics, providing capabilities to perform algebraic manipulations, solve equations, and work with calculus, among other mathematical tasks. It is a computer algebra system written in pure Python, designed to be easily extensible and to provide a comprehensive set of tools for symbolic computation.
import sympy as sym
For example, we can calculate the eigenvectors and values from the matrix above also computer-analytically
= sym.Matrix(matrix).eigenvects()
eigenvalues_and_vectors
print("The eigenvalues are {} and {}".format(eigenvalues_and_vectors[0][0], eigenvalues_and_vectors[1][0]))
print("The eigenvalues are {} and {}".format(eigenvalues_and_vectors[0][2][0], eigenvalues_and_vectors[1][2][0]))
The eigenvalues are 2 and 3
The eigenvalues are Matrix([[-1], [1]]) and Matrix([[1], [0]])
Another use case is to differentiate a function using SymPy in Python using the diff
function. Here’s an example:
# Define the variable
= sym.symbols('x')
x
# Define the function
= x**3 + 2*x**2 + x + 1
f
# Differentiate the function with respect to x
sym.diff(f, x)
\(\displaystyle 3 x^{2} + 4 x + 1\)
To represent a vector ( x ) using the eigenvectors of a matrix ( A ) as a basis, follow these steps:
If ( A ) is a square matrix, and it has a full set of linearly independent eigenvectors, we can decompose it as: [ A = V V^{-1} ] where: - ( V ) is the matrix whose columns are the eigenvectors of ( A ), - ( ) is the diagonal matrix containing the corresponding eigenvalues of ( A ), - ( V^{-1} ) is the inverse of ( V ) (assuming the eigenvectors are linearly independent).
The eigenvectors of ( A ) form a basis for the vector space. To represent ( x ) in this new basis, express ( x ) as a linear combination of the eigenvectors of ( A ).
Let ( v_1, v_2, , v_n ) be the eigenvectors of ( A ). You want to express: [ x = c_1 v_1 + c_2 v_2 + + c_n v_n ] where ( c_1, c_2, , c_n ) are the scalar coefficients that correspond to the projection of ( x ) onto each eigenvector ( v_i ).
If ( V ) is the matrix whose columns are the eigenvectors of ( A ), then you can find the coefficients ( c ) by solving the following equation: [ x = V c ] where ( c = [c_1, c_2, , c_n]^T ).
To solve for ( c ), multiply both sides by ( V^{-1} ): [ c = V^{-1} x ] Thus, the coefficients ( c ) represent the vector ( x ) in the eigenvector basis.
Once you have the coefficients ( c ), you can reconstruct ( x ) as: [ x = V c ] where ( V ) is the matrix of eigenvectors and ( c ) is the vector of coefficients.
To represent ( x ) in the eigenvector basis of ( A ): 1. Compute the matrix ( V ) of eigenvectors of ( A ). 2. Find the coefficients ( c = V^{-1} x ). 3. ( x ) can then be written as ( x = V c ), where ( c ) represents ( x ) in the eigenvector basis.
There are many word combinations in the literature that broadly refer to the kind of science we will be exploring in this course. Take, for example, the word combination,
Coupled Social-Ecological Systems Modeling.
Your task is to write a Python function that randomly generates alternative names for this kind of science. Tip: Start by considering alternatives for each part of the word combination above.
# ...
The easiest way to save a notebook as a PDF file for sharing is to print it via your browser’s print dialogue.
See also 1 Introduction to Python and Jupyter Notebooks and 01.01-Getting-Started-with-Python-and-Jupyter-Notebooks, which served as valuable sources for this tutorial.↩︎
see 2 Data structures – Introduction to Data Science with Python for a more detailed exposition.↩︎
Comments
In Python code cells, comments begin with
#
. They serve to clarify your code. Nonetheless, it’s best not to use them excessively. Your code should ideally be clear and comprehensible on its own, without the need for excessive comments.📝 Exercise
Write a comment in the cell below.