Python

Vous pouvez tester en ligne les exemples grâce aux sites suivant :

Lancement

Compilation

Python parcourt le fichier source pour :

  • vérifier la syntaxe, y compris à l’intérieur des fonctions et des classes

  • vérifier la cohérence de l’indentation du code

Plus d’information sur l’indentation est disponible en bas de cette page.

Exécution

Le progamme est maintenant exécuté ligne à ligne :

  • Seules sont exécutées les instructions du niveau global (sans indentation)

  • Lorsque le mot clef def est rencontré, le programme note le nom de la fonction, sans l’exécuter

    • Pour exécuter une fonction, il faut qu’elle soit appelée dans le code

    • Pour appeler une fonction, il faut qu’elle ait été définie avant dans le code

a = 5                   # création et initialisation de la variable a
toto()                  # erreur car la fonction toto() est inconnue à ce niveau
def toto():             # définition de la fonction toto()
   print("toto")
toto()                  # cet appel ne déclenche plus d'erreur

Librairie

L’import d’une librairie consiste à charger dans le programme les fonctions et les variables disponibles dans cette librairie.

import math

c = math.cos(math.pi)

Certaines librairies sont si importantes qu’elles sont redivisées en sous-librairies :

import numpy

t = numpy.random.rand(3)

Il est possible d’utiliser un alias pour simplifier le code :

import numpy as np

t = np.random.rand(3)

Avertissement

Évitez la syntaxe : from numpy import * car elle est source de nombreux problèmes.

Mutable

Un objet mutable peut être modifié après sa création : on peut modifier son contenu sans le recréer. Dans le cas contraire, on parle d’objet immutable.

mutable

Listes, dictionnaires

immutable

Entiers, chaînes de caractères, tuples

Une variable n’est ni mutable ni immutable, c’est l’objet auquel elle fait référence qui est mutable/immutable.

Structures de contrôle

Rappel en fin de cette page

  • Branchements

  • Boucles

Indiquez la valeur de la variable tot à la fin du code suivant :

tot = 0
for i in range(3,11,4):
   if i > 5 :
       tot += i

Parcours d’un container

for e in data :

Syntaxe du foreach en Python

On peut ainsi parcourir les éléments de tout container dit « iterable » : liste, tuple, dictionnaire…

Les containers

Rappel en fin de cette page

  • Liste

  • Tuple

  • Dictionnaire

Pour chaque affirmation, indiquez si elle est vraie ou fausse.

La fonction len() donne le nombre d’éléments d’une liste, d’un tuple ou d’un dictionnaire

On peut modifier le nombre d’éléments d’un tuple.

La fonction print() liste les informations stockées dans un container

On peut créer une liste contenant des dictionnaires

Un tuple contient uniquement des éléments de même type

Dans une liste, on peut insérer un élément uniquement en fin de liste

Il est possible de savoir si une clef est déjà utilisée dans un dictionnaire

En associant une valeur à une clef, la valeur précédemment associée à cette clef est écrasée

La syntaxe suivante est valide : x,y = 1,2

Variable globale

A l’intérieur d’une fonction :

  • Vous avez accès en lecture à toutes les variables globales

  • Pour modifier une variable globale, il faut utiliser le mot-clef global :

g = 4
def fnt():
    global g    # autorise la modification de la variable globale
    g = 6
fnt()
print(g)       # >> 6

Avertissement

Si vous oubliez le mot-clef global, cela va entrâiner la création d’une variable locale g. Il n’y aura aucun message d’erreur et le programme ne fonctionnera pas comme attendu.

Passage

Tout est objet

En Python, tout est objet. Ainsi les variables correspondent uniquement à des références. Pour tester cela, nous utilisons la fonction id(..) qui retourne l’adresse mémoire associé à la référence.

a = 6                    # a est une référence vers un objet de type int valant 6
print(type(a), id(a))    # <class 'int'>   139792681752000
b = a                        # b référence le même objet
print(id(a))             # 139792681752000

Passage et retour

La mécanique de base

Chaque paramètre d’une fonction correspond à une variable locale qui fait référence à l’objet passé en argument.

L = [1,2]
def fnt(LL):
  LL = [3,4]
fnt(L)
print(L)   >> [1,2]

Avertissement

En utilisant ce mécanisme, aucun retourn n’est possible !

Option 1

Cependant, une liste reste un objet mutable, on peut donc modifier son contenu :

L = [1,2]
def fnt(LL):
  LL[:] = [3,4]
fnt(L)
print(L)   >> [3,4]

Option 2

On peut aussi retourner le résultat:

L = [1,2]
def fnt():
  return [3,4]
L = fnt()
print(L)   >> [3,4]

Clonage

Problématique

Dans l’écriture L=[1,2] la variable L référence la liste [1,2]. En écrivant T = L, la variable T référence la liste initiale et à aucun moment une nouvelle liste a été créée. Ainsi, on constate ce genre de problématique :

L = [1, 2]
T = L
L.append(3)
print(L)         >> [1, 2, 3]
print(T)             >> [1, 2, 3]
../_images/ex11.png

Effectuer une copie

La fonction copy() crée une nouvelle liste et copie les références contenues dans la liste initiale. La nouvelle liste est indépendante de la première, si on insère un élément, il n’apparait que dans celle-la :

L = [1, 2, 3]
T = L.copy()
T.append(4)

print(L)    >> [1, 2, 3]
print(T)    >> [1, 2, 3, 4]]
../_images/ex21.png

Mais attention, il s’agit d’une copie superficielle où seules les références ont été dupliquées :

L = [ [1,2,3], [4,5,6] ]
T = L.copy()

L[0][0] = 9

print(L)     >> [ [9,2,3], [4,5,6] ]
print(T)     >> [ [9,2,3], [4,5,6] ]
../_images/ex3.png

Effectuer une copie profonde

Pour dupliquer un objet en construisant des copies de manière récursive, il faut utiliser la fonction copy.deepcopy() :

import copy
L = [ [1,2], [3,4] ]
T = copy.deepcopy(L)
L[0][0] = 9
L[1][1] = 8

print(L)     >> [ [9,2], [3,8] ]
print(T)     >> [ [1,2], [3,4] ]     Les deux listes L et T sont maintenant indépendantes
../_images/ex4.png

Pour chaque affirmation, indiquez si elle est vraie ou fausse.

Le mot clef global permet d’avoir un accès en écriture vers une variable globale

Pour effectuer une copie profonde, il faut utiliser la fonction copy()

Les listes sont de type mutable

Les tuples sont de type mutable

../_images/rappels.jpg

Rappels

Indentation

La traditionnelle paire d’accolades a été remplacée en Python par l’indentation. Ainsi, les sources en Python ont une apparence très structurée. En effet, chaque sous-bloc de code est introduit en ajoutant une tabulation ou plusieurs espaces supplémentaires par rapport au bloc parent. A l’intérieur du même bloc, l’indentation doit être identique. Voici le style généré :

a = 4                       # définition d'une variable dans le bloc principal
def toto():                 # définition de la fonction toto()
    print("toto")           # indentation => cette ligne appartient au corps de la fonction toto()
b = 5                       # l'indentation est revenue au niveau de la ligne de l'instruction a=4 => cette ligne appartient au bloc principal
def titi():                 # définition de la fonction titi()
    for i in range (10):    # indentation supplémentaire => cette boucle appartient à la fonction titi()
        print(i)            # indentation supplémentaire => la fonction print() est dans le corps de boucle
        print(i)            # l'indentation est identique à celle de la ligne précédente => on reste dans le corps de boucle
    toto()                  # l'indentation diminue et revient au niveau de la boucle for, cette instruction sera appelée après la fin de la boucle
titi()                      # l'indentation diminue et revient au niveau le plus à gauche, cette ligne appartient au bloc principal

Structures de contrôle

Les branchements

  • Il n’est pas nécessaire de parenthèser les conditions contrairement aux autres langages type C++/Java

  • Les mots-clefs and, or et not désignent les opérateurs booléens

  • Les constantes booléennes sont : True et False

if i == 3 or i == 5 :

Double test avec un OU logique

Les boucles

for i in range(5):

i : 0 1 2 3 4

for i in range(3,10,2):

i : 3 5 7 9

Les containers

La liste

Une liste permet :

  • de stocker des éléments de types hétérogènes

  • d’accéder aux éléments par un index entier : L[i]

  • de modifier les éléments qu’elle contient : L[i] = …

  • d’ajouter ou de retirer des éléments dynamiquement

En contrepartie de cette souplesse, elles sont bien plus lentes que les vecteurs du C++ ou les arrayList du Java.

L = [1, 2, 5, 2]

Création et initialisation

L = [1, "toto", 3.1415, [1,2] ]

Création d’une liste contenant des types hétérogènes

L.append(5)

Ajout de l’élément 5 en fin de liste

L.insert(2,9)

Insère la valeur 9 à l’index 2

L.remove(2)

Retire la première valeur 2 trouvée dans la liste

L.pop()

Retourne et retire le dernier élément de la liste

len(L)

Nombre d’éléments dans la liste

L.sort()

Trie la liste inplace

L[0]

Accès par indexation

L.clear()

Vide la liste

[1, 2] + [4 , 5]

L’opérateur + concatène les deux listes : [1, 2, 4, 5]

print(L)

Affiche le contenu de la liste

Les tuples

Une tuple est une restriction des listes :

  • impossible d’insérer ou de retirer des éléments : le tuple est immutable, il est donc de taille fixe

  • impossible de modifier ses éléments après la création : T[i] =

Cependant, les éléments mutables d’un tuple peuvent voir leur contenu modifier :

T = (1, [2, 3], 5)

T[1].append(4) >> T = (1, [2, 3, 4], 5)

L = (1, 2, [4,5])

Création d’un tuple contenant des types hétérogènes

len(L)

Nombre d’éléments dans le tuple

L[0]

Accès par indexation

L[2][0] += 1

Accès à la valeur 4 de la liste [4,5] ⇒ L devient (1, 2, [5,5])

print(L)

Affiche le contenu du tuple

x, y, z = L

Dépaquetage : x = 1, y = 2 et z = [5,5]

K = x, y

Empaquetage : K = (1,2)

x, y, z = 1, 2, 3

Initialisation rapide de 3 variables

Les tuples permettent de retourner plusieurs éléments comme résultat d’une fonction. Cette facilité est très pratique :

def toto():
    return 1,"toto"

a,b = toto()

Les dictionnaires

Un dictionnaire associe une valeur à une clef. Ainsi, il permet :

  • de stocker des éléments de types hétérogènes

  • d’accéder à un élément par une clef k de type quelconque : D[k]

  • d’ajouter, modifier ou retirer des éléments dynamiquement

, clefs comme valeurs peuvent être de types hétérogènes. Ainsi un dictionnaire correspond à une de liste dont les index peuvent être autre chose que des entiers. Les dictionnaires offrent plus de souplesse que les listes, au détriment de la performance. Voici les syntaxes des dictionnaires :

Exemples

D = {}

Création d’un dictionnaire à partir d’une paire d’accolades

D[“PV”] = 4

Associe la valeur 4 à la clef PV

D[“PV”] = 8

Modifie la valeur associée à la clef PV

D[9] = “ARC”

Associe la valeur “ARC” à la clef 9

print(D)

Affiche le contenu du dictionnaire : {“PV”: 4, 9: “ARC”}

if “PV” in D

Teste si la clef PV existe dans le dictionnaire

L = {“PV”: 4, “OR”: 2}

Initialisation d’un dictionnaire par passage de paires clefs/valeurs

len(L)

Indique le nombre d’entrées dans le dictionnaire