# Introduction to Python and Jupyter notebooks

## Contents

# 1. Introduction to Python and Jupyter notebooks#

*Estimated time to complete:* 60 to 90 minutes.

## 1.1. Introduction#

Welcome to the online materials for this online course on programming in Python for mathematical computing (a.k.a. *scientific computing*).

This first unit is an introduction to some basic features of the Python software that we will be using. Specifically, we use Python 3, and even more specifically, Python version 3.9 or higher.

We start directly with Jupyter notebooks via the tool *JupyterLab* as a way to use Python interactively like a scientific calculator, and aim to work with these notebooks as much as possible.

Later, we will also learn the more advanced code development tools offered by the *Integrated Development Environment* Spyder.
This supports both both interactive use of Python and also working with files of Python code: creating, opening and editing files, running and debugging code, and so on.
It has more advanced tools for developing Python code than the Jupyter notebook system, so for more substantial programming tasks it can be better to develop code within Spyder — even if that code is then transferred into a notebook for final presentation.

However, the use of any Integrated Development Environment [“IDE”] is somewhat optional; it will be possible to work almost entirely with Jupyter notebooks. That for example would allow working with just the web-browser based system CoCalc

**Aside:** There are other IDE’s for Python, such as IDLE; that is the original IDE for Python and is pre-installed in some computers (Mac’s at least) but it is very rudimentary compared to Spyder.

## 1.2. Getting Python software for scientific computing#

I suggest that you get Anaconda for you own computers, even if you also have access to it via computers on-campus. Get the “current” version based on Python 3; more specifically, version 3.9 or higher.

The various components like the iPython console, Spyder and Jupyter can also be got separately (follow those links), but that involves getting under the hood with some command line installation activity, and maybe even compiling from source code.

A possible alternative is to use the purely online resource CoCalc, which has a free “trial” version. This provides Jupyter notebooks, but not all the other useful tools like Spyder.

## 1.3. “Python Scientific”: adding three packages that make Python more useful for scientific computing#

Anaconda and its components JupyterLab and Spyder include a collection of useful resources beyond basic Python: the *packages*

Numpy for numerical and scientific computing, particularly for working with vectors and matrices,

Matplotlib for producing graphs of numerical data and functions, and

Scipy which provides some more advanced scientific computing tools, such as for optimization and solving ordinary differential equations.

This combination is often called *Python Scientific*.

## 1.4. Online resources#

There is a vast array of free online tutorials and documentation for Python and the other tools that we are using, such as

Real Python and its “Start Here” page — these notes often link to the Real Python site for supplementary reading.

The official Python documentation site and in particular the tutorial for Python version 3.9; comprehensive but a bit harder to read. (For now I suggest reading about this version 3.9 rather than any more recent ones, because currently some installations of Anaconda and Spyder are still based on this version, and anything said here also works for the newer versions.

These resources might be useful sometimes, but our direction is a bit different: aiming at what is most important to a mathematics student, rather than a computer science student. For our “Python Scientific” orientation, there is a comprehensive but more advanced reference, the Scipy Lecture Notes, as both a website and a downloadable PDF book.

There are also official sites for Python and the most important packages:

but these are not so readable as some of the sources listed above.

## 1.5. Using Python as a calculator #

For some tasks, Python can be used much like a scientific calculator (and later, like a graphing scientific calculator); that is how we will work for this section.

There are multiple ways of doing this, and I invite you to experiment with them all at some stage:

In Jupyter notebooks (like this one), which can be accessed from within the Anaconda Navigator by opening

*JupyterLab*With the “bare” IPython console; this is available in many ways, including from the Anaconda Navigator by opening

*Qt Console*With Spyder, which can be accessed from within the Anaconda Navigator by opening

*Spyder*; within that, there is an interactive Python console frame at bottom-right.

I suggest learning one tool at a time, by using a Jupyter notebook for now; however if you wish to also try some or all of the alternatives above, go ahead!

## 1.6. Creating a course folder and a Jupyter notebook#

Create a folder within your home folder or on your desktop named something like “

*PythonScientific*”; all files for this course should be put in there. (If you use a different name, please use one that starts with a letter and contains only letters, digits, dashes, and underscores — no spaces or other punctuation. Other names can work for now, but these restrictions can help to avoid problems later!)Open Anaconda and within Anaconda-Navigator, launch

*JupyterLab*.In the file system navigator frame at left, get to that folder (

*PythonScientific*or whatever).Use the File menu at top-left to create a new notebook.

It will have a single cell of type “Code”, as indicated at top-center; use that menu to change it to type “Markdown”, which is for entering text.

In this cell, add a

*title*, your*name*and the*date*; see the title cell at the top of this notebook.

Note that:the single hash “# ” (followed by a space) at the start of a line makes that line a level 1 heading.

surrounding text with single asterisks is for

*italic text*.surrounding text with pairs of asterisks is for

**boldface text**.surrounding text with angle brackets <…> creates a link to an email address.

Next, add a new cell below this, using the “+” button above; this is automatically a Code cell, and you could put all subsequent code in that cell. However it would be better to spread the code over multiple cells, by adding more: one for each example and exercise. Also, I encourage you to intersperse Markdown cells with explanatory text — that will be good practice in the longer run.

Here is an example of the text to put into a simple code cell:

## 1.7. Running some or all cells in a notebook#

Running a Code cell executes its Python code; running a Markdown cell formats its content for nicer output. There are several ways to do this:

The “Play” (triangle icon) button above runs the current cell, and moves to the next cell as “current”.

The menu “Run” above has various options — hopefully self-explanatory, at least after some experimentation.

To get a Markdown cell back from nicely formatted “display mode” back to “edit mode”, double click in it.

## 1.8. Notes on organization and presentation#

For all exercises throughout this course, record both your input and the resulting output, in a document that you will submit for feedback and then grading.

We want a written or typed record of all our work and results, and I also encourage you to make notes of other things that you learn, beyond what must be submitted — they will help later in the course!

For now, one option is to make hand-written notes and then scan them to PDF for uploading, but it is better to create files directly, and Jupyter notebooks will usually be the best way to do that.

Also note that — as just described above and for every document that you submit, hand-written or electronic — start with:

A

*title*,*your name*(possibly also with your email address), andthe

*date*, of the**current version**.

(See the Title Cell above for example.)

Revision dates will become important, as you will often be submitting successive revisions and refinements: our goal is mastery of each topic, not partial credit!

## 1.9. Arithmetic#

This is mostly easy stuff, but with a few quirks of notation and such to note.

First, let us see how to run Python code with the following famous formula. In a new code cell in notebook, type the following and run it with the “play” button or using the “Run” menu.

If you wish to also start learning the command line interface:

open Spyder (or another Python tool like IPython),

type the following into the

*IPython console*(at bottom-right in the Spyder window), andpress “Return” or “Enter” to get the result.

```
2 + 2
```

```
4
```

No prize for predicting the above result, but division of two integers requires a little care:

```
11 / 4
```

```
2.75
```

Here Python 3 gives a real number answer, whereas some programing languages always given an integer answer for the division of integers, by rounding down (“truncating”) if necessary. (In fact, the older version Python 2 does that, which is one reason that we avoid using it!)

When you want the truncated, integer answer, use a double slash:

```
11 // 4
```

```
2
```

and to get the remainder, use the percent sign!

```
11 % 4
```

```
3
```

With multiplication, the only catch is that *there is no multplication sign on the keyboard*, so the asterisk is used instead:

```
7 * 4
```

```
28
```

There is no way to type superscripts either, so exponentiation uses a double-asterisk (not the “caret” or up-arrow, as used in some other programming languages and calculators):

```
2**5
```

```
32
```

Numbers with exponents can be expressed using this exponential notation, but note how Python outputs them:

```
5.3*10**21
```

```
5.3e+21
```

```
7*10**-8
```

```
7e-08
```

This “e” notation is the standard way to describe numbers with exponents, and you can input them that way too.

When printing numbers, Python decides if the number is big enough or small enough to be worth printing with an exponent:

```
2e-10, 3E-5, 3e-4, 5e+4, 10000000000, 6e15, 6e16
```

```
(2e-10, 3e-05, 0.0003, 50000.0, 10000000000, 6000000000000000.0, 6e+16)
```

**Aside:** note that either “e” or “E” can be used in input of exponents.
However in most contexts, Python is case sensitive; we will see an example soon.

## 1.10. Naming quantities and displaying values#

It often helps to give named to quantities, which is done with assignment statements. For example, to solve for \(x\) in the very simple equation \(ax + b = 0\) for given values of \(a\) and \(b\), let us name all three quantities:

```
a = 3
b = 7
x = -b/a
```

Running the above cell just computes the three values with no output;
to see the values we use the function `print`

:

```
print(a, b, x)
```

```
3 7 -2.3333333333333335
```

That output does not expian things very clearly; we can add explanatory text to the printed results in several ways. Most basically:

```
print('For a =', a, 'and b =', b, 'the solution of ax + b = 0 is', x)
```

```
For a = 3 and b = 7 the solution of ax + b = 0 is -2.3333333333333335
```

The above prints six items — three text strings (each quoted), three numbers — separated by commas.

There is an alternative notation for such output, called “f-strings”, which use braces to specify that the value of a variable (or formula) be inserted into a string of text to display:

```
print(f'For a = {a} and b = {b} the solution of ax + b = 0 is {x}')
```

```
For a = 3 and b = 7 the solution of ax + b = 0 is -2.3333333333333335
```

In this example each pair of braces inserts the value of a variable; one can instead put a formula in there. So in fact we could skip the variable \(x\) entirely:

```
print(f'For a = {a} and b = {b} the solution of ax + b = 0 is {-b/a}')
```

```
For a = 3 and b = 7 the solution of ax + b = 0 is -2.3333333333333335
```

We can also display the equation more directly:

```
print(f'The solution of {a} x + {b} = 0 is {-b/a}')
```

```
The solution of 3 x + 7 = 0 is -2.3333333333333335
```

## 1.11. Some mathematical functions and constants: module `math`

#

Python includes many **modules** and **packages** that add useful defintions of functions, constants and such, and for us, the most fundamental is `math`

, which is a standard part of Python.

(Later will see some other modules that are not part of standard Python, but which Anaconda, Jupyter Lab and Spyder add to the basic collection:
`numpy`

, `matplotlib`

and `scipy`

mentioned above, and also `pylab`

, which combines much but not all of `numpy`

and `matplotlib`

.)

We can access specific items with an `import`

command;
to start with, two variables containing famous values:

```
from math import pi, e
```

**Aside:** we will soon learn about the package `numpy`

and then mostly use that instead of `math`

. I mention `math`

for now because it is a core part of Python whereas `numpy`

is a separate “add-on”, and you should be aware of `math`

if only because many references on doing mathematical stuff with Python will refer to it.)

Amongst many other things, `math`

gives our two favorite trancendental numbers, accurate to about 16 significant digits:

```
print(f'pi is approximately {pi}')
```

```
pi is approximately 3.141592653589793
```

```
print(f'e is approximately {e}')
```

```
e is approximately 2.718281828459045
```

Each is accurate to about 16 significant digits; that is the precision of the 64-bit number system standard in most modern computers.

### Names (like “e” and “pi”) are case-sensitive#

We can now return to the comment above about case sensitivity. Compare the results of the following two input lines:

```
print(f'e = {e}')
```

```
e = 2.718281828459045
```

```
print(f'E = {E}')
```

```
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Input In [20], in <cell line: 1>()
----> 1 print(f'E = {E}')
NameError: name 'E' is not defined
```

### Some `math`

functions#

Module `math`

also provides a lot of familiar mathematical functions

```
from math import sin, cos, cosh
```

which can be used like this:

```
sin(pi/4)
```

```
0.7071067811865475
```

```
cos(pi)
```

```
-1.0
```

```
cosh(0)
```

```
1.0
```

#### Notes#

**All**Python functions need parentheses around their arguments; no lazy shortcuts with trig. functions and such.Trig. functions use radians, not degrees.

## 1.12. Wild imports (mostly avoid!) versus spelling things out explicitly#

There is a shortcut that alows importing all quantities from a module; above we could have used

```
from math import *
```

which means “use everything in this module”, and is called a *wild import*.

However it is usually better and safer to specify explicitly the items that you will use, as done above.

A third “middle way” is to import the module (rathe than items from it) and then refer to items by their “full names” with a dot notation “module.item”. For example, with

```
import math
```

we get access to many functions such as `tan`

, but need to adress it by its full name `math.tan`

:

```
print(f"tan(pi/4) = {math.tan(pi/4)}")
```

```
tan(pi/4) = 0.9999999999999999
```

If we had not already imported `pi`

above, its full name `math.pi`

would also be needed, as in:

```
print(f"tan(pi/4) = {math.tan(math.pi/4)}")
```

```
tan(pi/4) = 0.9999999999999999
```

**Aside:** The imperfection of computer arithmetic becomes clear:
the exact value is 1 of course.
However, the precision of about 16 decimal places is far greater than for any experimental measurement, so this is usually not a problem in practice.

These more specific approaches to importing are highly recommended when creating files and programs; wild imports are best only used as a convenience when working interactively, using Python like a scientific calculator.

One advantage of importing items specifically “by name” is that it is then unambiguous where a given item was imported from, even if multiple `import`

commands are used.
For example, we will see later than there are both `math.cos`

and `numpy.cos`

, and they behave differently in some situations.

Another reason for explicit imports is for internal efficiency in storage and execution time; wild imports can potentially load thousands of items from a large module when only a few are used.

## 1.13. Logarithmic functions#

There is also a function `log`

in module `math`

, but which base does it use?

```
math.log(10)
```

```
2.302585092994046
```

```
math.log(e)
```

```
1.0
```

Evaluating these two expressions reveals that “log()” is the *natural logarithm*, base \(e\);

what mathematicians usually call “\(\ln\)”.

## 1.14. Exercises#

### Exercise A#

It is time to explore: try to find the base 10 logarithm.

A big hint: look at the following, which is yet another logarithm; one of particular interest in computer science.

```
math.log2(64)
```

```
6.0
```

### Powers and roots#

A square root can of course be computed using the 1/2 power, as with

```
16**0.5
```

```
4.0
```

but this function is important enough to have a named form provided by module `math`

:

```
math.sqrt(2)
```

```
1.4142135623730951
```

### Exercise B#

Here is a *wrong* way to use the exponential notation in an attempt to compute a square root: explain what goes wrong!

```
16**1/2
```

```
8.0
```

### Exercise C: Devising, evaluating and modifying formulas in Python#

It is time to practice with creating basic Python commands for mathematical expressions.

a) With the above information, warnings and examples in mind, evaluate \(\displaystyle \frac{1 + \sqrt{2}}{2 \pi}.\) (The correct answer is 0.384…)

b) [If using Spyder/IPython,] explore IPython’s command history and editing features, and use these to evaluate \(\displaystyle \frac{1 - \sqrt{2}}{2 \pi}\)
by modifying the previous formula, *without* typing the entire new expression from scratch.

### Exercise D: Putting this work into a file, and submitting for feedback#

Put your work so far into a Jupyter notebook.

For Exercises A and B, put your verbal answers into Markdown cells in the notbook.

For Exercise C, it is also worth adding some verbal explanation (again in a Markdown cell) along with the Python code and its output.

Then submit that notebook file; if using OAKS, submit it to the dropbox for this section.

**Reminder: The goal is mastery (not partial credit)**

I expect you to ask questions about how to do these tasks, but trying hands-on first is the best way to start; I will always give feedback and the opportunity to revise and perfect your work; the goal is working towards mastery of each topic.