Premiers types¶

Entiers¶

On peut faire des calculs sur les entiers avec les opérateurs classiques

In [1]:
1+3
Out[1]:
4
In [2]:
5-4
Out[2]:
1
In [3]:
4*5
Out[3]:
20

La puissance est ** et pas ^ qui dénote le ou exclusif.

In [4]:
2**3
Out[4]:
8
In [5]:
2^3
Out[5]:
1
In [6]:
1001^1100
Out[6]:
1957

Le quotient de la division euclidienne est // et le reste %. La division normale elle renvoit un nombre à virgule flottante

In [7]:
123//11
Out[7]:
11
In [8]:
123%11
Out[8]:
2
In [9]:
123/11
Out[9]:
11.181818181818182

On peut tester les types via la fonction type

In [10]:
type(11)
Out[10]:
int

Nombres à virgules flottantes¶

On a ici aussi les opérations artithmétiques usuelles.

In [11]:
1.5+1.3
Out[11]:
2.8
In [12]:
15.0-5
Out[12]:
10.0
In [13]:
14.*3.
Out[13]:
42.0
In [14]:
14./3.
Out[14]:
4.666666666666667
In [15]:
14.//3.
Out[15]:
4.0
In [16]:
2.5**3.4
Out[16]:
22.54218602980021

Chaînes de caractères¶

Outre les chaines de caractères on introduit aussi les premières variables via l'opérateur d'affectation =

In [17]:
message = "Première chaine de caractères"
In [18]:
type(message)
Out[18]:
str

On peut aussi utiliser des triples guillemets pour une chaine de plusieurs lignes

In [19]:
nouvelle = """
Nouvelles chaine de caractères.
On garde les sauts de lignes.
    Et éventuellement les alinéas.
"""

La fonction print permet d'afficher les chaines de caractères (et autres variables)

In [20]:
print(message)
Première chaine de caractères
In [21]:
print(nouvelle)
Nouvelles chaine de caractères.
On garde les sauts de lignes.
    Et éventuellement les alinéas.

On a accès à différentes fonctionnalités via la syntaxe suivante

In [22]:
message.capitalize()
Out[22]:
'Première chaine de caractères'
In [23]:
message.upper()
Out[23]:
'PREMIÈRE CHAINE DE CARACTÈRES'

Dans le notebook on pourra explorer les différentes possibilités en appuyant sur TAB après message.. On pourra aussi utiliser cette fonctionnalité pour compléter les noms de variables et de fonctions. On n'hésitera donc pas à utiliser des noms relativement longs et descriptifs.

On pourra aussi voir les arguments et des renseignements simples sur les fonctions en tapant sur MAJ+TAB, à l'intérieur des parenthèses d'un appel de fonctions.

Finalement si après un nom de fonction ou de variable on rajoute ?, on obtiendra une aide plus détaillé.

In [24]:
message.encode()
Out[24]:
b'Premi\xc3\xa8re chaine de caract\xc3\xa8res'

Listes¶

On explore ici le premier conteneur. Il s'agit d'un conteneur dynamique permettant de stocker des objets hétérogène.

In [25]:
ll = [1,2,3,4]
type(ll)
Out[25]:
list
In [26]:
print(ll)
[1, 2, 3, 4]

On peut accéder aux différents éléments via l'opérateur []

In [27]:
ll[0]
Out[27]:
1
In [28]:
ll[3]
Out[28]:
4
In [29]:
ll[3] = 5
print(ll)
[1, 2, 3, 5]

On voit que les indices commencent à 0 On peut utiliser des indices négatifs pour parcourir la liste dans l'autre sens

In [30]:
print(ll)
print(ll[-1])
[1, 2, 3, 5]
5

On a là encore beaucoup de fonctionnalités

In [31]:
ll.append(5)
print(ll)
[1, 2, 3, 5, 5]
In [32]:
x = ll.pop()
print(ll)
print(x)
[1, 2, 3, 5]
5
In [33]:
ll.reverse()
print(ll)
[5, 3, 2, 1]

On pourra aussi utiliser des fonctions qui permettent de ne pas modifier la liste mais d'en renvoyer une nouvelle.

In [34]:
print(ll)
print(sorted(ll))
print(ll)
[5, 3, 2, 1]
[1, 2, 3, 5]
[5, 3, 2, 1]

Echanges de variables¶

Si on veut échanger le contenu de plusieurs variables on a une syntaxe permettant de le faire sans variables intermédiaires.

In [35]:
a, b = 1, 2
print(a,b)
1 2
In [36]:
a, b = b , a
print(a,b)
2 1
In [37]:
a,b,c = 1, 2, 3
print(a,b,c)
1 2 3
In [38]:
a, b, c = b, c, a
print(a,b,c)
2 3 1

On a des possibilités plus avancées avec des listes à gauches

In [42]:
liste = [[1, 2], [3, 4]]
print("la liste vaut : ", liste)
a, b = liste
print("a contient : ", a)
print("b contient : ", b)
la liste vaut :  [[1, 2], [3, 4]]
a contient :  [1, 2]
b contient :  [3, 4]

On pourra regarder toutes les possibilités sur le site python.org à unpacking par exemple

In [43]:
liste = list(range(6))
print(liste)
[0, 1, 2, 3, 4, 5]
In [44]:
a, *b, c = liste
print("a contient : ", a)
print("b contient : ", b)
print("c contient : ", c)
a contient :  0
b contient :  [1, 2, 3, 4]
c contient :  5

Variables et Objets¶

Il ne faut en aucun cas penser en terme de variable contenant des objets, mais plutôt comme des variables ayant des noms mais pas de type pointant vers des objets ayant des types mais pas de noms.

In [51]:
a = [1, 2, 3, 4, 5]
b = [1, 2, 3, 4, 5]

print("les deux variables ont la même valeur :", a == b)

print(a)
print(b)

print("Mais les objets sont distincts")
a.append(6)
print(a)
print(b)
les deux variables ont la même valeur : True
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
Mais les objets sont distincts
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
In [53]:
a = [1, 2, 3, 4, 5]
b = a
print("les deux variables on la même valeur :", a==b)
print(a)
print(b)

print("cette fois ci il n'y a qu'un seul objet sous jacent")
a.append(6)
print(a)
print(b)

print("On peut tester cette identité de l'objet sous jacent de la façon suivante")
print(a is b)
les deux variables on la même valeur : True
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
cette fois ci il n'y a qu'un seul objet sous jacent
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]
On peut tester cette identité de l'objet sous jacent de la façon suivante
True

Structuration du code¶

Pour les différentes structurations les blocs commencent pas : et sont délimités via l'indentation.

Boucle for¶

Elle permet de parcourir tous les conteneurs et autres objets itérables...

In [54]:
liste = [1, 2, 3, 4, 5, 6, 7]
for x in liste:
    print(x)
1
2
3
4
5
6
7
In [55]:
for i in range(5, 20):
    print(i, " : ", i**2)
5  :  25
6  :  36
7  :  49
8  :  64
9  :  81
10  :  100
11  :  121
12  :  144
13  :  169
14  :  196
15  :  225
16  :  256
17  :  289
18  :  324
19  :  361

On a une syntaxe permettant facilement créer une liste/conteneur à partir d'un autre conteneur, la compréhension de liste.

In [58]:
carres = [x**2 for x in range(1, 11)]
print(carres)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [59]:
cubes = [x**3 for x in range(1, 11)]
print(cubes)
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

On peut également itérer sur plusieurs listes en parallèles.

In [60]:
differences = [y-x for x,y in zip(carres, cubes)]
print(differences)
[0, 4, 18, 48, 100, 180, 294, 448, 648, 900]

Test¶

On peut utiliser entre autres les opérateurs de comparaisons : ==, !=, <, >, <=, >=, `is

In [62]:
a, b = 1, 0
if a == b:
    print("a est égal à b")
elif a < b:
    print("a est strictement plus petit que b")
else:
    print("a est strictement plus grand que b")
a est strictement plus grand que b
In [63]:
a = [1, 2, 3]
b = a 
if a is b:
    print("a et b pointent vers le même objet")
elif a == b:
    print("a et b ont même valeur mais pointent vers des objets différents")
else:
    print("a et b ont des valeurs différentes")
    
a et b pointent vers le même objet

On peut aussi composer des tests avec and et or

In [64]:
a, b = -1, 1
if (a != b) and (a**2 == b**2):
    print("a et b sont opposés")
a et b sont opposés

Finalement on peut tester sur le type de donnée par exemple avant d'effectuer une certaine action dessus.

In [66]:
a = 1
if isinstance(a, int):
    print("a est entier")
elif isinstance(a, float):
    print("a est un nombre à virgule flottante")
elif isinstance(a, bool):
    print("a est un booléen")
a est entier

Fonctions¶

On peut regrouper des séquences d'actions dans une fonction via la syntaxe suivante.

In [71]:
def double(x):
    return x*2
In [72]:
double(5)
Out[72]:
10
In [73]:
double(5.0)
Out[73]:
10.0
In [74]:
double([1,2])
Out[74]:
[1, 2, 1, 2]

On notera que les arguments ne sont pas typés par défaut et que l'action réalisé peut dépendre de l'argument fourni.

On peut également fournir des valeurs par défaut via la syntaxe suivante.

In [75]:
def puissance(x,p=2):
    return x**p
In [76]:
puissance(2, 3)
Out[76]:
8
In [77]:
puissance(3)
Out[77]:
9

On peut fournir une explication rapide sur la fonction via une chaine de caractère sur la deuxième ligne qui sera fourni entre autre via l'appel MAJ+TAB

In [81]:
def puissance_bizarre(x):
    """Renvoit x**2 si x est pair et x**3 si x est impair"""
    if x % 2 == 0:
        return x**2
    else:
        return x**3
In [82]:
puissance_bizarre(2)
Out[82]:
4
In [83]:
puissance_bizarre(3)
Out[83]:
27

Exemples¶

On va calculer le pgcd de deux nombres via l'algorithme d'Euclide¶

In [86]:
def euclide(a, b):
    """Calcul de pgcd(a,b) via l'algorithme d'Euclide"""
    if a < b:
        b,a = a,b
    while b != 0:
        a, b = b, a%b
    return a
In [87]:
euclide(3,2)
Out[87]:
1
In [88]:
euclide(2*3*5*7, 3*5*7*11)
Out[88]:
105

On peut voir sur les exemples suivants que le comportement de la fonction est perfectible, on pourra essayer de l'améliorer.

In [89]:
euclide(-5, -2)
Out[89]:
-1
In [90]:
euclide(1.5, 0.3)
Out[90]:
5.551115123125783e-17

Racine par la méthode de Héron¶

In [98]:
def racine(a):
    """On va calculer approximativement la racine carrée de a via l'algorithme de Héron"""
    x = a
    for i in range(10):
        x = (x+a/x)/2
    return x
In [99]:
racine(2)
Out[99]:
1.414213562373095
In [100]:
racine(3)
Out[100]:
1.7320508075688772

Là encore le comportement de la fonction est perfectible, en particulier le nombre d'itérations devrait être adapté selon a.

In [101]:
racine(10**8)
Out[101]:
97997.34463768976

Suite de Fibonacci¶

In [102]:
def fibo(n):
    """Calcul des n premiers termes de la suite de Fibonacci"""
    resultat = [0, 1]
    while len(resultat) < n:
        resultat.append(resultat[-1]+resultat[-2])
    return resultat
In [103]:
fibo(10)
Out[103]:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
In [104]:
fibo(20)
Out[104]:
[0,
 1,
 1,
 2,
 3,
 5,
 8,
 13,
 21,
 34,
 55,
 89,
 144,
 233,
 377,
 610,
 987,
 1597,
 2584,
 4181]

Primalité¶

In [116]:
def est_premier(n):
    """Renvoit True si n est premier, False sinon"""
    if n<0:
        n = -n
    if n<2:
        return False
    for i in range(2, n//2+1):
        if n%i == 0:
            return False
    return True
In [117]:
for x in range(1, 30):
    print(x, " est-il premier? ", est_premier(x))
1  est-il premier?  False
2  est-il premier?  True
3  est-il premier?  True
4  est-il premier?  False
5  est-il premier?  True
6  est-il premier?  False
7  est-il premier?  True
8  est-il premier?  False
9  est-il premier?  False
10  est-il premier?  False
11  est-il premier?  True
12  est-il premier?  False
13  est-il premier?  True
14  est-il premier?  False
15  est-il premier?  False
16  est-il premier?  False
17  est-il premier?  True
18  est-il premier?  False
19  est-il premier?  True
20  est-il premier?  False
21  est-il premier?  False
22  est-il premier?  False
23  est-il premier?  True
24  est-il premier?  False
25  est-il premier?  False
26  est-il premier?  False
27  est-il premier?  False
28  est-il premier?  False
29  est-il premier?  True
In [118]:
def pourcentage_premiers(n):
    """Renvoit le pourcentage de nombres premiers entre 1 et n"""
    nombre = 0
    for x in range(1, n+1):
        if est_premier(x):
            nombre += 1
    return nombre*100/n
In [119]:
pourcentage_premiers(20)
Out[119]:
40.0
In [120]:
pourcentage_premiers(100)
Out[120]:
25.0
In [121]:
pourcentage_premiers(1000)
Out[121]:
16.8

Suite de Collatz¶

In [124]:
def Collatz(x, n):
    """Calcul des n premiers termes de la suite de Collatz initialisée par x"""
    def regle_Collatz(a):
        if a%2 ==0:
            return a//2
        else:
            return 3*a+1
    resultat = [x]
    while len(resultat) < n:
        resultat.append(regle_Collatz(resultat[-1]))
    return resultat
In [125]:
Collatz(11, 20)
Out[125]:
[11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2]
In [126]:
Collatz(5, 20)
Out[126]:
[5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2]
In [127]:
Collatz(12, 20)
Out[127]:
[12, 6, 3, 10, 5, 16, 8, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4, 2, 1, 4]

Paquets supplémentaires¶

De nombreuses fonctionnalités sont disponibles avec python, mais contenues dans des paquets supplémentaires qu'il faut importer.

In [128]:
import math
In [129]:
math.sqrt(2)
Out[129]:
1.4142135623730951
In [130]:
math.pi
Out[130]:
3.141592653589793
In [132]:
math.tan(math.pi/3)
Out[132]:
1.7320508075688767

Là encore une fois un module importé on pourra l'explorer via TAB après (dans notre cas) math.

In [133]:
import random as rd
In [134]:
aleatoires = [rd.random() for x in range(10)]
In [135]:
print(aleatoires)
[0.6585203401892438, 0.704766049017758, 0.491071072662999, 0.6360126880832518, 0.9295895457139004, 0.4778416845567399, 0.598169210402367, 0.5971943328551151, 0.46083573425381574, 0.3493387255750082]
In [136]:
entiers_aleatoires = [rd.randint(-10, 10) for x in range(20)]
In [137]:
print(entiers_aleatoires)
[-4, 6, 8, -3, 9, 7, 6, -7, 10, -7, -4, -2, 9, 9, 10, -6, 4, -6, -6, -9]

On pourra consulter par exemple python.org pour avoir un aperu de la quantité de paquets inclus automatiquement avec python.

De nombreux paquets supplémentaires sont disponibles via pip ou conda dans pyzo ou autres distributions.

Exercices¶

On pourra par exemple coder des fonctions :

  • Déterminant les triplets pythagoriciens de nombres entre 1 et n
  • Déterminer les sous-groupes de Z/nZ
  • Calculer $\pi$ en lançant des points alétoirement dans $[0,1]^2$ et en comptant la proportion de ceux qui tombent dans le cercle unité.
  • On pourra consulter aussi les problèmes de https://projecteuler.net/archives