# 3. Short Review on Python Programming¶

## 3.1. Programming and Data Structures¶

The notebook for the first
lecture introduced
some basic mathematical computations using *SageMath*. Among the many
things that one can do with *SageMath* include the execution of a
sequence of instructions. You many have observed this in the yesterday’s
notebook. The *SageMath* computer algebra system is in fact an extension
of the Python programming language, and allows, with a few exceptions,
the use of Python programming constructs. In this notebook, we will
briefly discuss how to use the Python programming language within
*SageMath*.

Hopefully you should be aware that one should avoid using Python keywords as variable or function names since this will cause programming. The list of keywords is available by:

```
import keyword; keyword.kwlist
```

```
2*3;3*4;4*5 # one comment, 3 results
```

In addition to these keywords, we have the constants `None`

(empty
value, named `NULL`

in other languages), `True`

and `False`

, and
several functions predefined by Python or *SageMath* like `len()`

,
`cos()`

and `integrate()`

. It is better not to use these as variable
names, otherwise some functionalities might no longer be available. The
interpreter knows some additional commands, like quit to exit the Sage
session. We will discover other commands like `time`

or `timeit`

later.

### 3.1.1. Function Calls¶

To evaluate a function, its arguments should be put inside parentheses —
for example `cos(pi)`

— or in the function call without argument
`reset()`

. However, the parentheses are superfluous for a command: the
instructions `print 6*7`

and `print(6*7)`

are equivalent. In Python
3, `print()`

is a function and thus requires parentheses.

### 3.1.2. More About Variables¶

As seen previously, *SageMath* denotes the assignment of a value to a
variable by the equal sign `=`

. The expression to the right of the
equal sign is first evaluated, then its value is saved in the variable
whose name is on the left. Thus we have:

```
y = 3; y = 3 * y + 1; y = 3 * y + 1; y
```

The three first assignments change the value of the variable `y`

without any output, the last command prints the final value of `y`

.

The `del x`

command discards the value assigned to the variable `x`

,
and the function call `reset()`

recovers the initial *SageMath*
state. Several variables can be assigned *simultaneously*, which
differs from *sequential assignments* `a = b; b = a`

```
a, b = 10, 20 # (a, b) = (10, 20) and [10, 20] are also possible
```

```
a, b = b, a
a,b
```

The assignment `a, b = b, a`

is equivalent to swapping the values of a
and b using an auxiliary variable:

```
temp = a; a = b; b = temp # equivalent to: a, b = b, a
```

The following trick swaps the values of a and b without any auxiliary variable, using additions and subtractions:

```
x, y = var('x, y'); a = x ; b = y
```

```
a, b
```

```
a = a + b ; b = a - b ; a = a - b
```

```
a,b
```

The instruction `a = b = c = 0`

assigns the same value, here `0`

, to
several variables; the instructions `x += 5`

and `n *= 2`

are
respectively equivalent to `x =x+5`

and `n = n*2`

.

The comparison between two objects is performed by the double equal sign `==:

```
2 + 2 == 2^2, 3 * 3 == 3^3
```

Click here if you want to go back to the table of content of this notebook. Otherwise, continue to the next Section.

## 3.2. Algorithmics¶

The paradigm of *structured programming* consists in designing a
computer program as a finite sequence of instructions, which are
executed in order. Those instructions can be **atomic** or **composed**:
an example of atomic instruction is the assignment of a value to a
variable a composed instruction, like a loop or a conditional, is made
up from several instructions, themselves atomic or composed.

### 3.2.1. Loops/ Enumeration Loops¶

An enumeration loop performs the same computation for all integer values of an index : the following example outputs the beginning of the multiplication table by 7:

```
for k in [1..5]:
print 7*k # block containing a single instruction
# The colon symbol “:” at the end of the first line starts the instruction block
```

In this example, the repeated instruction block contains a single
instruction (namely **print**), which is indented to the right with
respect to the **for** keyword. A block with several instructions has
its instructions written one below the other, with the same indentation.

The block positioning is important: the two programs below, which differ in the indentation of a single line, yield different results.

```
S = 0
for k in [1..3]:
S = S+k
S = 2*S
S
```

```
S = 0
for k in [1..3]:
S = S+k
S = 2*S
S
```

On the left the instruction **S = 2*S** is executed only once at the end of the loop, while on the right it is executed at every iteration, which explains the different results:

**While Loops**. The other kind of loops are the while loops. Like the
enumeration loops, they execute a certain number of times the same
sequence of instructions; however, here the number of repetitions is not
known a priori, but depends on a condition. The *while loop*, as its
name says, executes instructions while a given condition is fulfilled.
The following example computes the sum of the squares of non-negative
integers whose exponential is less or equal to i.e.,

```
S = 0; k =0 # The sum S starts to 0
while e^k<=10^6: # e^13 <= 10^6 < e^14
S = S + k^2
k = k+1
S
```

The above instruction block contains two assignments: the first one accumulates the new term, and the second one moves to the next index. Those two instructions are indented in the same way inside the while loop structure.

### 3.2.2. Functions and Procedures¶

General Syntax.As in other computer languages, the *SageMath* user can
define her/his own procedures or functions, using the `def`

command
whose syntax is detailed below. We call a function (resp. procedure) a
sub-program with zero, one or several arguments, which returns (resp.
does not return) a result. Let us define the function
.

```
def fct2 (x,y):
return x^2 + y^2
a = var('a')
fct2(a,2*a)
```

By default, all variables appearing in a function are considered local variables. Local variables are created at each function call, destroyed at the end of the function, and do not interact with other variables of the same name. In particular, global variables are not modified by the evaluation of a function having local variables of the same name:

```
def foo(u):
t = u^2
return t*(t+1)
t= 1; u= 2
foo(3),t,u
```

It is possible to modify a global variable from within a function, with the global keyword:

```
a = b =1
def f(): global a; a = b= 2
f();a,b
```

Iterative and Recursive Methods.

As we have seen above, a user-defined function is a sequence of instructions. A function is called recursive when duringits evaluation, it calls itself with different parameters. The factorial sequence is a toy example of recursive sequence:

The two following functions yield the same result for a nonnegative integer argument n; the first function uses the iterative method with a for loop, while the second one is a word-by-word translation of the above recursive definition:

```
def fact1 (n):
res = 1
for k in [1..n]: res = res*k
return res
```

```
def fact2 (n):
if n == 0: return 1
else: return n*fact2(n-1)
```

**Global List Operations**: The addition operator `+`

concatenates two
lists, and the multiplication operator `*`

, together with an integer,
performs an iterated concatenation:

```
L = [1, 2, 3] ; L + [10, 20, 30]
```

```
4 * [1, 2, 3]
```

The concatenation of the two sub-lists L[:k] and L[k:] reconstructs the original list. This explains why the left bound p of a sub-list L[p:q] is included

```
L = 5*[10, 20, 30]; L[:3]+L[3:] == L
```

The operator made from two points “..” makes it easy to construct integerlists without explicitly enumerating all elements, and can be mixed with isolatedelements:

```
[1..3, 7, 10..13]
```

We explain below how to build the image of a list under a function, and a sub-list of a list. The corresponding functions are map and filter, together with the [..for..x..in..]construction. Mathematics often involve lists made by applying a function to its elements:

The map command builds this “map”: the following example applies the trigonometric function cos to a list of usual angles:

```
map (cos, [0, pi/6, pi/4, pi/3, pi/2])
```

A user-defined function — with def — or a lambda-expression might also be used as first argument of map; the following command is equivalent to the above, using the function :

```
map (lambda t: cos(t), [0, pi/6, pi/4, pi/3, pi/2])
```

The lambda command is followed by the parameters separated by commas, and the colon must be followed by exactly one expression, which is the function result (without the returnkeyword). A lambda expression may contain a test, whence the following functions are equivalent:

fctTest1 = lambda x: res1 if cond else res2

def fctTest2 (x):

if cond: return res1

else: return res2

As a consequence, the three following map commands are equivalent, the composition being expressed in different ways:

```
map (lambda t: N(cos(t)), [0, pi/6, pi/4, pi/3, pi/2])
```

```
map (N, map (cos, [0, pi/6, pi/4, pi/3, pi/2]))
```

```
map (compose(N, cos), [0, pi/6, pi/4, pi/3, pi/2])
```

The filter command builds the sub-list of the elements satisfying a given condition. To get all integers in 1, …, 57 that are prime:

```
filter (is_prime, [1..57])
```

The test condition might be defined inside the filter command, as in thefollowing example which finds by exhaustive search all fourth roots of 7 modulothe prime 37; this equation has four solutions 3, 18, 19 and 34:

```
p = 37 ; filter (lambda n: n^4 % p == 7, [0..p-1])
```

Another way to build a list is using the comprehension form [..for..x..in..]; both commands below enumerate odd integers from 1 to 31:

```
map(lambda n:2*n+1, [0..15])
```

```
[2*n+1 for n in [0..15]]
```

The comprehension command is independent of the for loop. Associated with the if condition, it yields an equivalent construction to filter:

```
filter(is_prime, [1..55])
```

```
[p for p in [1..55] if is_prime()]
```

In the two following examples, we combine the if and filter tests with the comprehension for to determine a list of primes congruent to 1 modulo 4, then a list of squares of prime numbers:

```
filter (is_prime, [4*n+1 for n in [0..20]])
```

```
[n^2 for n in [1..20] if is_prime(n)]
```

In the first case the **is_prime** test is performed after the
computation of , while in the second one the primality
test is done before the computation of the square .

Click here if you want to go back to the table of content of this notebook. Otherwise, continue to the next Section.

## 3.3. Graphics in Two Dimensions¶

**Graphical Representation of a Function**: To draw the graph of a
symbolic or Python function on an interval `[a, b]`

, we use
`plot(f(x), a, b)`

or the alternative syntax `plot(f(x), x, a, b)`

.

```
plot(x * sin(1/x), x, -2, 2, plot_points=500)
```

Among the numerous options of the plot command, we mention the following:

plot_points (default value 200): minimal number of computed points;

xmin and xmax: interval bounds over which the function is displayed;

color: colour of the graph, either a RGB triple, a character string such as’blue’, or an HTML colour like ’#aaff0b’;

detect_poles (default value False): enables to draw a vertical asymptoteat poles of the function;

alpha: line transparency;

thickness: line thickness;

linestyle: style of the line, either dotted with ’:’, dash-dotted with ’-.’,or solid with the default value ’-’.

To visualise the graph, we assign the graphical object to a variable, say g, then we use the show command; in addition we can give bounds for the y-axis (g.show(ymin=-1, ymax=3)) or choose the aspect ratio (g.show(aspect_ratio=1) to have equal scales for x and y).

The graph obtained may be exported using the save command into several formats defined by the suffixes .pdf, .png, .ps, .eps, .svg and .sobj

g.save(name, aspect_ratio=1, xmin=-1, xmax=3, ymin=-1, ymax=3)

Let us draw on the same graphics the sine function and its first Taylor polynomials at 0.

```
def p(x, n):
return(taylor(sin(x), x, 0, n))
xmax = 15 ; n = 15
g = plot(sin(x), x, -xmax, xmax)
for d in range(n):
g += plot(p(x, 2 * d + 1), x, -xmax, xmax,color=(1.7*d/(2*n), 1.5*d/(2*n), 1-3*d/(4*n)))
g.show(ymin=-2, ymax=2)
```

We can also create an animation, to see how the Taylor polynomials approximate better and better the sine function when their degree increases. To keep the animation, it suffices to save it in the gif format.

```
a = animate([[sin(x), taylor(sin(x), x, 0, 2*k+1)]\
for k in range(0, 14)], xmin=-14, xmax=14,\
ymin=-3, ymax=3, figsize=[8, 4])
a.show(); a.save('/home/yae/Desktop/plots/animation.gif')
```

```
t = var('t')
x = cos(t) + cos(7*t)/2 + sin(17*t)/3
y = sin(t) + sin(7*t)/2 + cos(17*t)/3
g = parametric_plot((x, y), (t, 0, 2*pi))
g.show(aspect_ratio=1)
```

### 3.3.1. Data Plot¶

To construct a bar graph, two distinct functions are available. On the one hand, bar_chart takes as input an integer list and draws vertical bars whose height is given by the list elements (in the given order). The width option enables us tochoose the bar width.

```
bar_chart([randrange(15) for i in range(20)])
```

```
bar_chart([x^2 for x in range(1,20)], width=0.2)
```

On the other hand, to draw the histogram of a random variable from a list offloating-point numbers, we use the plot_histogram function. The list values arefirst sorted and grouped into intervals (the number of intervals is given by the option binswhose default value is 50). The height of each bar being proportional to the number of corresponding values.

```
liste = [10 + floor(10*sin(i)) for i in range(100)]
bar_chart(liste)
```

### 3.3.2. More on plotting¶

```
g(x) = sin(x)/x;
diff(g(x), x)
```

```
limit(g(x), x=0); # evaluate the limit
```

```
plot(g(x), (x,-30,30),figsize=4)
```

```
gplot = plot(g, (-10,10), legend_label=r'$g(x) = %s$'%latex(g(x)),figsize=5)
gplot
```

```
hplot = plot(g,(-10,10), color='darkgreen', legend_label=r'$h(x)=\cos(x)$',figsize=5, gridlines=[range(10),srange(0,1,0.1)])
hplot
```

## 3.4. Exercises¶

Given the lists:

list_a = ["Evans", "Yae", "Jan"] list_b = ["Mary", "Rosemond", "Jjulian", "Frances"]

Create the least possible list of pairs {(a, b) | a :raw-latex:`\in `list_a, b:raw-latex:`in `list_b}

Given the list [(“Evans”, “Ocansey”), (“Yae”, “Gaba”), (“Jeff”, “Sanders”), (“Karthy”, “Green”)] where the first and second element of each tuple in the list is the first and last name. Write a program that creates two tuples, first_name and last_name which will collects all the first names and last names of each tuple in the list.

< 1. Introduction to Sagemath| Table of contents | 3. Sum of squares and plotting >