# Python¶

## Notation¶

When writing computer commands that you can type, the font will change
to `command`

. For example, `x=2**3.4/5`

is a command that can be
typed in.

When we talk about a general command, or some piece of missing data that
you should complete, we will use angle brackets as in `<command>`

or
`<variable>`

. For example, `<location>`

could mean
`"Southampton"`

.

When showing actual commands as typed into Python, they will start with
`In [<number>]:`

. This is the notation used by the IPython console.
The `<number>`

allows you to refer to previous commands more easily.
The output associated with that command will start with
`Out [<number>]:`

.

When displaying code, certain commands will appear in different colours. The colours are not necessary. They highlight different types of command or variable. When using the spyder editor you may find the colours match up and are useful: if not, either ignore them or switch them off.

## The console - Python as calculator¶

Start with using Python as a calculator. Look at the *console* in the
bottom right part of spyder. Here we can type commands and see a result.
Simple arithmetic gives the expected results:

```
In [1]:
```

```
2+2
```

```
Out[1]:
```

```
4
```

```
In [2]:
```

```
(13.5*2.6-1.4)/10.2
```

```
Out[2]:
```

```
3.3039215686274517
```

If we want to raise a number to a power, say , the notation
is `**`

:

```
In [3]:
```

```
2**4
```

```
Out[3]:
```

```
16
```

There is an issue with division. If we divide an integer by an integer,
Python `3.X`

will do *real* (floating point) division, so that:

```
In [4]:
```

```
5/2
```

```
Out[4]:
```

```
2.5
```

However, Python `2.X`

will do division in the integers:

```
In []: 5/2
Out []: 2
```

If you are using Python `2.X`

and want the division operator to behave
in this way, start by using the command

```
In [5]:
```

```
from __future__ import division
```

Then:

```
In [6]:
```

```
5/2
```

```
Out[6]:
```

```
2.5
```

If you really want to do integer division, the command is `//`

:

```
In [7]:
```

```
5//2
```

```
Out[7]:
```

```
2
```

Further mathematical commands, even things as simple as or , are not included as part of basic Python:

```
In [8]:
```

```
log(2.3)
```

```
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-8-83d4dd34e7bf> in <module>()
----> 1 log(2.3)
NameError: name 'log' is not defined
```

```
In [9]:
```

```
sin(1.4)
```

```
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-9-6dd12df070cd> in <module>()
----> 1 sin(1.4)
NameError: name 'sin' is not defined
```

First, note the way that errors are reported: we’ll see this a lot, and there’s useful information there to understand. It’s telling us

- Where the problem occurred
- What the problem is

The language Python uses takes some getting used to, but it’s worth the effort to read these messages, and think about what it’s trying to say. Here it’s pointing to the line where the problem happened, and saying “I don’t understand what this command is!”.

Going back to the mathematics, we obviously want to be able to compute
more mathematical functions. For this we need a *module* or *package*.

## Importing modules and packages¶

Anything that isn’t provided by the base Python can be provided by modules and packages. A module is a file containing functions and definitions that we can include and use in our code. A package is a collection of modules. They’re not included by default, to reduce overhead. They’re easy to write - we will write our own later - and easy to include.

To use a package we must *import* it. Let’s look at the `math`

package.

```
In [10]:
```

```
import math
```

```
In [11]:
```

```
math.log(2.3)
```

```
Out[11]:
```

```
0.8329091229351039
```

```
In [12]:
```

```
math.sin(1.2)
```

```
Out[12]:
```

```
0.9320390859672263
```

To use the package we’ve typed `import <package>`

, where in this case
`<package>`

is `math`

. Then we can use functions from that package
by typing `<package>.<function>`

, as we have here when `<function>`

is either `log`

or `sin`

.

The “dot” notation may seem annoying, and can be avoided by specifying
what functions and constants we want to use. For example, we could just
get the `log`

function and use that:

```
In [13]:
```

```
from math import log
```

```
In [14]:
```

```
log(2.3)
```

```
Out[14]:
```

```
0.8329091229351039
```

However, the “dot” notation is useful, as we often find the same symbol
or name being used for many different purposes. For example, the
`math`

package contains the mathematical constant as
`math.e`

:

```
In [15]:
```

```
math.e
```

```
Out[15]:
```

```
2.718281828459045
```

But there is also the electron charge, usually denoted , which
is in the `scipy.constants`

package:

```
In [16]:
```

```
import scipy.constants
```

```
In [17]:
```

```
scipy.constants.e
```

```
Out[17]:
```

```
1.6021766208e-19
```

To avoid these name clashes we can import something *as* a different
name:

```
In [18]:
```

```
from math import e
```

```
In [19]:
```

```
from scipy.constants import e as charge_e
```

```
In [20]:
```

```
e
```

```
Out[20]:
```

```
2.718281828459045
```

```
In [21]:
```

```
charge_e
```

```
Out[21]:
```

```
1.6021766208e-19
```

You will often see this method used to shorten the names of imported modules or functions. For example, standard examples often used are:

```
In [22]:
```

```
import numpy as np
```

```
In [23]:
```

```
import matplotlib.pyplot as plt
```

The commands can then be used by typing `np.<function>`

, or
`plt.<function>`

, which saves typing. We would encourage you *not* to
do this as it can make your code less clear.

## Variables¶

A *variable* is an object with a name and a value:

```
In [24]:
```

```
x = 2
```

In standard programming all variables must have a value (although that
value may be a placeholder to say “this variable doesn’t have a
reasonable value *yet*”). Only symbolic packages can mirror the
analytical method of having a variable with no specific value. However,
code can be written *as if* the variables had no specific value.

For example, we cannot write

```
In [25]:
```

```
x = y**2
```

```
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-25-9736a48890b4> in <module>()
----> 1 x = y**2
NameError: name 'y' is not defined
```

as `y`

does not have a specific value yet. However, we can write

```
In [26]:
```

```
y = 3.14159627
```

```
In [27]:
```

```
x = y**2
```

```
In [28]:
```

```
print(x)
```

```
9.869627123677912
```

and get a sensible result, even though we have written the exact same
line of code, as now `y`

has a specific value.

### Warning¶

Note that we have defined the variable `x`

twice in rapid succession:
first as an *integer* (`x=2`

) and next as a *floating point number*,
or *float* (the computer’s implementation of a real number, using
`x=y**2`

, where `y`

is a float). Not all programming languages allow
you to do this. In a *statically typed* language you have to say whether
a variable will be an integer, or a float, or another type, before you
define it, and then it cannot change. Python is *dynamically typed*, so
any variable can have any type, which can be changed as we go.

## Variable names¶

A variable is an object with a name, but not just any name will do.
Python has rules which *must* be followed, and conventions that *should*
be followed, with a few gray areas.

Variables *must*

- not contain spaces
- not start with a number
- not contain a special character (such as
`!@#$%^&*()\|`

)

So the following are valid:

```
In [29]:
```

```
half = 1.0/2.0
```

```
In [30]:
```

```
one_half = 1.0/2.0
```

but the following are not:

```
In [31]:
```

```
one half = 1.0/2.0
```

```
File "<ipython-input-31-3d1440172542>", line 1
one half = 1.0/2.0
^
SyntaxError: invalid syntax
```

```
In [32]:
```

```
1_half = 1.0/2.0
```

```
File "<ipython-input-32-7867c2b402d6>", line 1
1_half = 1.0/2.0
^
SyntaxError: invalid syntax
```

```
In [33]:
```

```
one!half = 1.0/2.0
```

```
File "<ipython-input-33-d585fc045f28>", line 1
one!half = 1.0/2.0
^
SyntaxError: invalid syntax
```

Variables *should*

- be descriptive, ie say what their purpose is in the code
- be written entirely in lower case
- separate different words in the variable name using underscores

More detail can be found in PEP8.

Variables *may* contain some unicode characters, depending on Python
version and operating system. In Python `3`

you can include accents or
extended character sets in variable names:

```
rôle = 5
π = math.pi
```

However, these tricks are not always portable between different Python
versions (they aren’t guaranteed to work in Python `2`

), or different
operating systems, or even different machines. To ensure that your code
works as widely as possible, and that the methods you use will carry
over to other programming languages, it is recommended that variables do
not use any extended characters, but only the basic latin characters,
numbers, and underscores.

## Equality and variable assignment¶

One thing that may seem odd, or just plain *wrong* to a mathematician,
is two statements like

```
In [34]:
```

```
x = 2
```

```
In [35]:
```

```
x = 3
```

How can `x`

equal *both* 2 and 3? Mathematically, this is nonsense.

The point is that, in nearly every programming language, the `=`

symbol is not mathematical equality. It is the *assignment* operation:
“set the value of the variable (on the left hand side) equal to the
result of the operation (on the right hand side)”. This implies another
difference from the mathematical equality: we cannot flip the two sides
and the line of code mean the same. For example,

```
In [36]:
```

```
3 = x
```

```
File "<ipython-input-36-6f12c1f282a0>", line 1
3 = x
^
SyntaxError: can't assign to literal
```

immediately fails as `3`

is not a variable but a fixed quantity (a
*literal*), which cannot be assigned to. Mathematically there is no
difference between and ; in programming there is
a huge difference between `x=3`

and `3=x`

as the meaning of `=`

is
not the mathematical meaning.

To get closer to the standard mathematical equality, Python has the
`==`

operator. This compares the left and right hand sides and says
whether or not their values are equal:

```
In [37]:
```

```
x == 3.0
```

```
Out[37]:
```

```
True
```

However, this may not be exactly what we want. Note that we have
assigned `x`

to be the *integer* 3, but have compared its value to the
*float* 3.0. If we want to check equality of value and type, Python has
the `type`

function:

```
In [38]:
```

```
type(x)
```

```
Out[38]:
```

```
int
```

```
In [39]:
```

```
type(x) == type(3.0)
```

```
Out[39]:
```

```
False
```

```
In [40]:
```

```
type(x) == type(3)
```

```
Out[40]:
```

```
True
```

Direct comparisons of equality are often avoided for floating point numbers, due to inherent numerical inaccuracies:

```
In [41]:
```

```
p = 2.01
```

```
In [42]:
```

```
p**2-4.0401
```

```
Out[42]:
```

```
-8.881784197001252e-16
```

```
In [43]:
```

```
p**2 == 4.0401
```

```
Out[43]:
```

```
False
```

We will return to this later.

# Debugging¶

Making mistakes and fixing them is an essential part of both mathematics
and programming. When trying to fix problems in your code this process
is called *debugging*. As you’ve been following along with the code you
will have made “mistakes” as there are intentionally broken commands
above to show, for example, why `one!half`

is not a valid variable
(and you may have made unintentional mistakes as well).

There are a number of techniques and strategies to make debugging less painful. There’s more detail in later chapters, but for now let’s look at the crucial first method.

## Reading the error message¶

When you make a mistake Python tells you, and in some detail. When using IPython in particular, there is much information you can get from the error message, and you should read it in detail. Let’s look at examples.

A *syntax error* is when Python cannot interpret the command you have
entered.

```
In [44]:
```

```
one half = 1.0/2.0
```

```
File "<ipython-input-44-3d1440172542>", line 1
one half = 1.0/2.0
^
SyntaxError: invalid syntax
```

This example we saw above. The `SyntaxError`

is because of the space -
`one half`

is not a valid variable name. The error message says
`invalid syntax`

because Python can’t interpret the command on the
left of the equals sign. The use of the carat `^`

points to the
particular “variable” that Python can’t understand.

```
In [45]:
```

```
x = 1.0 / ( 2.0 + (3.0 * 4.5)
```

```
File "<ipython-input-45-da9f857ed183>", line 1
x = 1.0 / ( 2.0 + (3.0 * 4.5)
^
SyntaxError: unexpected EOF while parsing
```

This example is still a `SyntaxError`

, but the pointer (`^`

) is
indicating the end of the line, and the statement is saying something
new. In this statement `unexpected EOF while parsing`

, “`EOF`

”
stands for “end of file”. This can be reworded as “Python was reading
your command and got to the end before it expected”.

This usually means something is missing. In this case a bracket is missing - there are two left brackets but only one right bracket.

A similar example would be

```
In [46]:
```

```
name = "This string should end here...
```

```
File "<ipython-input-46-e75a715c38f0>", line 1
name = "This string should end here...
^
SyntaxError: EOL while scanning string literal
```

In this case the error message includes “`EOL`

”, standing for “end
of line”. So we can reword this message as “Python was reading your
command and got to the end of the line before the string finished”. We
fix this by adding a `"`

at the end of the line.

Finally, what happens if the error is buried in many lines of code? This isn’t the way we’d enter code in the console, but is how we’d deal with code in the notebook, or in a script or file:

```
In [47]:
```

```
x = 1.0
y = 2.3
z = 4.5 * x y + y
a = x + y + z
b = 3.4 * a
```

```
File "<ipython-input-47-8b0bd2354b36>", line 3
z = 4.5 * x y + y
^
SyntaxError: invalid syntax
```

We see that the error message points to the *specific line* that it
can’t interpret, *and* it says (at first) which line this is.

This is where Python doesn’t know the variable you’re trying to refer to:

```
In [48]:
```

```
my_variable = 6
my_variable_2 = 10
x = my_variable + my_variable_3
```

```
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-48-06bcebc035d2> in <module>()
1 my_variable = 6
2 my_variable_2 = 10
----> 3 x = my_variable + my_variable_3
NameError: name 'my_variable_3' is not defined
```

It usually means you’ve made a typo, or have referred to a variable before defining it (sometimes by cutting and pasting code around). Using tab completion is a good way of minimizing these errors.

Note that there is a difference between syntax errors and other errors.
Syntax errors are spotted by the code before it is run; other errors
require running the code. This means the format of the output is
different. Rather than giving the line number and using a carat
(“`^`

”) to point to the error, instead it points to the code line
using “`---->`

” and adds the line number before the line of code.

A range of “incorrect” mathematical operations will give errors. For example

```
In [49]:
```

```
1.0/0.0
```

```
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-49-fd44f356366a> in <module>()
----> 1 1.0/0.0
ZeroDivisionError: float division by zero
```

Obviously dividing by zero is a bad thing to try and do within the
reals. Note that the definition of floating point numbers *does* include
the concept of infinity (via “`inf`

”), but this is painful to use
and should be avoided where possible.

```
In [50]:
```

```
math.log(0.0)
```

```
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-50-7a32bd6f7959> in <module>()
----> 1 math.log(0.0)
ValueError: math domain error
```

A `ValueError`

generally means that you’re trying to call a function
with a value that just doesn’t make sense to it: in this case,
just can’t be evaluated when .

```
In [51]:
```

```
10.0**(10.0**(10.0**10.0))
```

```
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
<ipython-input-51-c25c175740ef> in <module>()
----> 1 10.0**(10.0**(10.0**10.0))
OverflowError: (34, 'Result too large')
```

An `OverflowError`

is when the number gets too large to be represented
as a floating point number.

Having read the error message, find the line in your code that it indicates. If the error is clear, then fix it. If not, try splitting the line into multiple simpler commands and see where the problem lies. If using spyder, enter the commands into the editor and see if the syntax highlighting helps spot errors.

# Exercise: Variables and assignment¶

## Exercise 1¶

Remember that . Compute , assigning the result to a sensible variable name.

## Exercise 2¶

Using the `math`

module, check your result for factorial.
You should explore the help for the `math`

library and its functions,
using eg tab-completion, the spyder inspector, or online sources.

## Exercise 3¶

Stirling’s approximation gives that, for large enough ,

Using functions and constants from the `math`

library, compare the
results of and Stirling’s approximation for
. In what sense does the approximation improve
(investigate the absolute error and the relative error
)?