Jupyter and Python

Note

You can download this example as a Python script: jupyter-python.py or Jupyter notebook: jupyter-python.ipynb.

Learning Objectives

After completing this chapter readers will be able to:

  • Run the Jupyter notebook software

  • Use magic commands in the Jupyter notebook

  • Create basic data types in Python

  • Create and use Python functions

  • Import Python modules

Introduction

The following is a brief introduction to Python and how to use Python from a Jupyter Notebook. There is much more to learn than what is covered here. This is just enough to get you started for the purposes of this book. You will need to seek out the many excellent learning materials online to learn more; some are provided at the end of this chapter.

The Jupyter Notebook

The Jupyter Notebook is an application that lets you execute code to as well as display text, mathematics, digital media, and HTML-CSS-Javascript-based outputs. The displayed elements can be embedded directly or generated by the executed code. This makes the Jupyter Notebook well suited for communicating content that is linked and driven by code. It allows you to edit the code interactively. Each page of this book is a Jupyter Notebook and can be downloaded and executed on your computer. Jupyter can execute code from many programming languages. Different kernels are used for each language and a notebook can, in general, only have a single kernel. This book will use the Python 3 kernel.

Using the Notebook

To start the Jupyter notebook application open a terminal (Linux/Mac) or command prompt (Windows), navigate to a desired working directory then type the following command:

jupyter notebook

A new window will open in your web browser where you can open an existing notebook or start a new one. Notebooks are organized with cells. You may have a code cell for inputting commands followed by its result cell which contains the output of the code. You may also have a text cell that contains static content written in Markdown. Markdown allows you to incorporate simple formatting and even things like mathematical equations using LaTeX notation, e.g. $a^2$ displays as \(a^2\). The cell type can be changed using a Jupyter drop-down menu.

There is the menu bar above for navigating a notebook but you will find the following keyboard shortcuts helpful:

  • Enter : Create a new line with in cell

  • Shift + Enter : Execute cell and advance to next cell

  • Ctrl + Enter : Execute cell in place (do not advance to the next cell)

  • Press esc (command mode) then h to display keyboard shortcuts

At times you might run code that gets stuck in an infinite loop or you might simply want to clear all your workspace variables and start over. To solve each of these problems you can click on the menu:

Kernel -> Interrupt

then

Kernel -> Restart

Magic Commands

These are special commands that only work in a Juypter notebook or an IPython session, as opposed to the normal Python interpreter. Magic commands are preceded by a % or %%. You can list available magic commands but using the magic command lsmagic.

%lsmagic
Available line magics:
%alias  %alias_magic  %autoawait  %autocall  %automagic  %autosave  %bookmark  %cat  %cd  %clear  %code_wrap  %colors  %conda  %config  %connect_info  %cp  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %killbgscripts  %ldir  %less  %lf  %lk  %ll  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %ls  %lsmagic  %lx  %macro  %magic  %mamba  %man  %matplotlib  %micromamba  %mkdir  %more  %mv  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %pip  %popd  %pprint  %precision  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %rm  %rmdir  %run  %save  %sc  %set_env  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%code_wrap  %%debug  %%file  %%html  %%javascript  %%js  %%latex  %%markdown  %%perl  %%prun  %%pypy  %%python  %%python2  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.

For example %whos will show the variables available in your namespace:

a = 5

%whos
Variable   Type    Data/Info
----------------------------
a          int     5

Need Help?

In case you’re lost help isn’t far. The following commands should provide assistance.

? displays an overview of the features available when typing in code cells in Jupyter notebooks (the cells are parsed by the IPython Python interpreter when using the Python kernel):

?

A quick reference for the special commands in Jupyter code cells can be viewed with:

%quickref

For details about any Python object in the namespace, append a ? to the variable or function (without ()). For example, help for the round() function can be found like so:

round?

Python

Python has become one of the world’s most popular programming languages. It is open source, free to use, and well suited for scientific and engineering programming needs. The following gives a brief introduction to the basics of Python.

Basic Data Types

Python has core builtin data types. The type() function shows you the type of any Python object. For example, here are the types of some integers, floating point numbers, and strings:

a = 5
b = 5.0
c = float(5)
d = 'dee'
e = 'e'
f = 2+3j
g = True

type(a), type(b), type(c), type(d), type(e), type(f), type(g)
(int, float, float, str, str, complex, bool)

Data Structures

Python offers several builtin data structures for grouping and organizing objects. Lists, tuples, and dictionaries are the most commonly used.

Lists

A list is a versatile container that holds objects in the order given. Lists are typically used to group similar items but may contain heterogeneous data types.

empty_list = []

string_list = ['lions', 'tigers', 'bears', 'sharks', 'hamsters']

int_list = [0, 1, 2, 3, 4]

int_list2 = list(range(5,10))

list_from_variables = [a, b, c, d, e]

list_of_lists = [empty_list,
                 string_list,
                 list_from_variables,
                 int_list,
                 int_list2]

Each of these can be displayed:

empty_list
[]
string_list
['lions', 'tigers', 'bears', 'sharks', 'hamsters']
int_list
[0, 1, 2, 3, 4]
int_list2
[5, 6, 7, 8, 9]
list_from_variables
[5, 5.0, 5.0, 'dee', 'e']
list_of_lists
[[],
 ['lions', 'tigers', 'bears', 'sharks', 'hamsters'],
 [5, 5.0, 5.0, 'dee', 'e'],
 [0, 1, 2, 3, 4],
 [5, 6, 7, 8, 9]]

Elements of a list are accessible by their index.

Warning

Beware that Python uses zero-based numbering, i.e. the first index value is 0.

string_list[0]
'lions'

Slices can be used to extract a contiguous subset:

string_list[1:4]
['tigers', 'bears', 'sharks']

Or subset patterns. This extracts every 2nd element:

int_list[::2]
[0, 2, 4]

To access an item in a nested list use successive square brackets:

list_of_lists[1][4]
'hamsters'

Lists are mutable, meaning after a list is created we can change, add, or remove elements. Here are several ways to modify a list:

int_list[2] = 222

int_list.append(5)

string_list.remove('lions')

list_from_variables.extend(int_list)

Note that the existing lists have been modified in-place:

int_list
[0, 1, 222, 3, 4, 5]
string_list
['tigers', 'bears', 'sharks', 'hamsters']
list_from_variables
[5, 5.0, 5.0, 'dee', 'e', 0, 1, 222, 3, 4, 5]

Tuples

Tuples share similarities with lists. The primary difference between a list and tuple is that tuples are not mutable. A tuple is good for organizing related data that may be of different types. Note that tuples are defined with parentheses, (), rather than square brackets.

joe_blow = (32, 'tall', 'likes hats')
joe_blow
(32, 'tall', 'likes hats')

Indexing works the same as lists:

joe_blow[1]
'tall'

Unlike lists, tuples are immutable. They cannot be changed once defined. Trying some of the mutating methods of lists results in errors on tuples:

joe_blow.append('married')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[24], line 1
----> 1 joe_blow.append('married')

AttributeError: 'tuple' object has no attribute 'append'
joe_blow[2] = 'not really a fan of hats'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[25], line 1
----> 1 joe_blow[2] = 'not really a fan of hats'

TypeError: 'tuple' object does not support item assignment

In Python, a function can return multiple values. These multiple outputs are packed into a tuple. Tuple unpacking assigns individual elements of a tuple to separate variables.

pets = ('elephant', 'cow', 'rock')

pet1, pet2, pet3 = pets

pet1
'elephant'

A peculiar thing about tuples in Python is defining a single element tuple. Note the trailing comma. This is necessary for Python to know you want a one-element tuple.

tuple_with_one_item = pet1,

tuple_with_one_item
('elephant',)

Dictionaries

A dictionary is an unordered set of key: value pairs. Much like a language dictionary where you look up a word and get its definition, in a Python dictionary you look up a key and get its value.

Any immutable object can be used as a key, any object can be a value. For example, here are strings as both keys and values:

dictionary0 = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}
dictionary0
{'key1': 'value1', 'key2': 'value2', 'key3': 'value3'}

or integers can be used as keys:

dictionary1 = {1: 'value1', 2: 'value2', 3: 'value3'}
dictionary1
{1: 'value1', 2: 'value2', 3: 'value3'}

The keys and values can be extracted separately using .keys() and .values() and converting to a list:

list(dictionary1.keys())
[1, 2, 3]
list(dictionary1.values())
['value1', 'value2', 'value3']

Individual items can be extracted with square brackets and the key:

cylinder = {'mass': 50, 'base': 10, 'height': 100}
cylinder['mass']
50

The zip() function is a convenient way to help generate a dictionary. It takes sequence objects and combines them into a list of tuples. We can subsequently use the list of four-element tuples to create a dictionary.

keys = ['mass01', 'inertia01', 'mass02', 'inertia02']
values = [10, 1, 50, 5]
dict(zip(keys, values))
{'mass01': 10, 'inertia01': 1, 'mass02': 50, 'inertia02': 5}

Functions

Python does not use braces, {}, or end statements to separate blocks of code. Rather, code blocks are initialized with colon, :, and defined by their indentation. It is convention to use four spaces (not tabs) for each level of indentation. Functions are defined and used like so:

def abs_value(A):
    if A < 0:
        A = -A
    return A

abs_value(-100)
100
abs_value(123)
123

This function returns two results:

def long_div(dividend, divisor):
    quotient = dividend // divisor  # // : floor division
    remainder = dividend % divisor  # % : modulo
    return quotient, remainder

Now you can use the function:

a = 430
b = 25

quo, rem = long_div(a, b)

quo, rem
(17, 5)

print() and .format() can be used to make custom text to display:

msg = '{} divided {} is {} remainder {}'.format(a, b, quo, rem)
print(msg)
430 divided 25 is 17 remainder 5

Modules

Modules add additional functionality not present in the default namespace of Python. Some modules are included with Python (builtin modules) and some are provided by other software packages and libraries you download and install. For example, the builtin sys module provides access to system-specific parameters and functions. You can check what Python version you are currently using by first importing the sys module and then accessing the .version variable:

import sys

print(sys.version)
3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) [GCC 12.3.0]

You can also import the version variable to have it included in the current namespace:

from sys import version

print(version)
3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) [GCC 12.3.0]

You will be using SymPy, NumPy, SciPy, and matplotlib further along in this book. These packages will consistently be imported like so:

import sympy as sm
import numpy as np
import matplotlib.pyplot as plt

This will allow you to keep the namespaces separate so that there are no variable name clashes. For example, SymPy, NumPy, and SciPy all have trigonometric functions:

sm.cos(12.0)
\[\displaystyle 0.843853958732492\]
np.cos(12.0)
0.8438539587324921

and there may be times when you want to use more than one version of cos() in a single namespace.

Learn More

More Jupyter

There are many introductory resources for learning to use Jupyter which can be found with search engines. As examples, this RealPython introduction is a good start (ignore the installation part, as you have it installed already from the instructions in this book):

https://realPython.com/jupyter-notebook-introduction/

This 7 minute video also gives the basics:

More Python

There are literally thousands of Python learning materials freely available on the web that fit many different needs. Here are a few recommendations for core Python for beginners: