I) Identité et Egalité, sur des chaines caractères et les listes

Ce cours TP porte sur les chaînes de caractère. Ce type est designé sous le nom de str dans python De façon générale, a ceci près qu'un str est in objet immuable, les str se comportent comme une list dont les éléments sont les caractères,

Ainsi, les deux codes suivants affichent la même chose :


In [1]:
for it in "chat":
    print(it)


c
h
a
t

In [2]:
for it in ["c","h","a","t"]:
    print(it)


c
h
a
t

In [3]:
"chat" + " chien"


Out[3]:
'chat chien'

In [4]:
"chat"[2]


Out[4]:
'a'

C'est un exemple de généricité, python possède un certain nombre d'opérations communes aux ensembles, quelque soit la nature de cet ensemble (une string est un ensemble de caractère, une liste est un ensemble d'éléments quelconques).

Les opérations en commun sont les suivantes :

  • addition
  • multiplication
  • boucle for
  • fonction len( ... )
  • accès aux éléments par indice
  • accès à un sous-ensemble par indice (revision prévue en TD aujourd'hui)

La principale différence est que les chaînes de caractères ne sont pas modifiables ! On ne peut donc PAS effectuer les opérations suivantes :

- suppression d'un élément (del liste[i])
- assignation à un élément (liste[i] = ...)
- ajout d'un élément (append pour une liste)

1. Différence entre identité et égalité

Il y a ici une notion très importante en informatique, celle de différencier la variable et sa valeur. Cette notion est particulièrement importante pour les listes, car on peut choisir de modifier l'un ou l'autre. Il faut également distinguer identité et égalité

Deux variables sont identiques si elles pointent vers la même valeur. Deux variables sont égales si leur valeurs sont égales. Deux variables identiques sont forcément égales.

Dans les deux exemples ci-dessous, dans le premier les deux variables liste_a et liste_b sont identiques et égales, dans le deuxième seulement égales.

On peut savoir si deux variables sont identiques en utilisant la fonction id ou avec l'opérateur is


In [5]:
liste_a = [1,2,3]
liste_b = liste_a
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
print( "liste_a == liste_b => ", liste_a == liste_b )
print( "liste_a is liste_b => ", liste_a is liste_b )


liste_a [1, 2, 3] 3054954636
liste_b [1, 2, 3] 3054954636
liste_a == liste_b =>  True
liste_a is liste_b =>  True

In [6]:
liste_a = [1,2,3]
liste_b = [1,2,3]
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
print( "liste_a == liste_b => ", liste_a == liste_b )
print( "liste_a is liste_b => ", liste_a is liste_b )


liste_a [1, 2, 3] 3018568716
liste_b [1, 2, 3] 3054972364
liste_a == liste_b =>  True
liste_a is liste_b =>  False

La différence est importante lorsque l'on modifie la valeur d'une des deux variables, on modifie les deux. Il faut ici aussi distinguer lorsque l'on modifie une variable ou lorsque l'on modifie sa valeur.

liste_a.append(4) modifie la valeur de la variable, celle-ci désigne toujours la même liste, mais celle-ci possède un élément en plus liste_a = liste_a + [4] modifie la variable, mais pas sa valeur précédente. Elle créé une nouvelle liste, issue de la concaténation de deux listes, et assigne cette valeur à liste_a

Dans les 4 cas suivants, on ajoute à chaque fois un élément à a, mais une fois sur deux en modifiant la variable et l'autre en modifiant sa valeur, et on distingue si liste_a et liste_b sont identiques ou seulement égales.


In [7]:
liste_a = [1,2,3]
liste_b = liste_a
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
liste_a.append( 4 )
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )


liste_a [1, 2, 3] 3054966412
liste_b [1, 2, 3] 3054966412
liste_a [1, 2, 3, 4] 3054966412
liste_b [1, 2, 3, 4] 3054966412

In [8]:
liste_a = [1,2,3]
liste_b = liste_a
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
liste_a = liste_a + [ 4 ]
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )


liste_a [1, 2, 3] 3018571372
liste_b [1, 2, 3] 3018571372
liste_a [1, 2, 3, 4] 3054969804
liste_b [1, 2, 3] 3018571372

In [9]:
liste_a = [1,2,3]
liste_b = [1,2,3]
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
liste_a.append( 4 )
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )


liste_a [1, 2, 3] 3018570220
liste_b [1, 2, 3] 3018569772
liste_a [1, 2, 3, 4] 3018570220
liste_b [1, 2, 3] 3018569772

In [10]:
liste_a = [1,2,3]
liste_b = [1,2,3]
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )
liste_a = liste_a + [ 4 ]
print( "liste_a", liste_a, id(liste_a) )
print( "liste_b", liste_b, id(liste_b) )


liste_a [1, 2, 3] 3054969932
liste_b [1, 2, 3] 3018571276
liste_a [1, 2, 3, 4] 3054972364
liste_b [1, 2, 3] 3018571276

Dans le cas des chaînes de caractère, la différence entre identité et égalité est peu importante et peu significative car on ne peut pas les modifier.

2. Délimiteurs des chaînes de caractères

En python, il existe trois façons de créer des chaines de caractères :


In [11]:
chaine_1 = "Hello world"
chaine_2 = 'Hello world'
chaine_3 = """Hello

Wolrd !"""
print("chaine_1 :", chaine_1)
print("chaine_2 :", chaine_2)
print("chaine_3 :", chaine_3)


chaine_1 : Hello world
chaine_2 : Hello world
chaine_3 : Hello

Wolrd !

Contrairement à d'autre langages, il n'y a pas différence de nature entre ses 3 façons de faire (usuellement le séparateur " " est utilisé pour les chaînes de caractère, et ' ' pour les caractères).
Utiliser un délimiteur permet d'utiliser les autres comme caractères normaux. Le délimiteur """ permet de créer des chaînes sur plusieurs lignes, ce que nous avons vus sous le nom de docstring.


In [12]:
print("l'éléphant")
print('il a dit "bonjour !".')
print("""l'éléphant a dit "bonjour !".""")


l'éléphant
il a dit "bonjour !".
l'éléphant a dit "bonjour !".

3. Accès aux sous-ensembles

Cet accès se fait avec la notation [a:b]. La borne a étant incluse et la borne b excluse.
On peut omettre l'une ou l'autre des bornes, dans ce cas cela signifira "depuis le début de la liste" ou "jusqu'à la fin de la liste".
On peut utiliser des indices négatifs.
A noter que cette notation est "permissive". Il n'y a pas d'erreur si a ou b dépasse les capacités de la liste.
De même si la position de a dans la liste se situe après b, ou correspond à b, cela renverra une liste vide, sans erreur.
Par exemple :


In [13]:
s = "elephant"
s1 = s[2:5] ## s1 vaut "eph"
print( s1 )

## Pour extraire la première moitié
print( s[:len(s)//2] )


eph
elep

In [14]:
s = "elephant"
s1 = s[:3] ## s1 vaut "ele"
print( s1 )


ele

In [15]:
s = "elephant"
s1 = s[5:] ## s1 vaut "ant"
print( s1 )


ant

In [16]:
s = "elephant"
s1 = s[:-2] ## s1 vaut "eleph"
print( s1 )


elepha

In [17]:
s = "elephant"
s1 = s[-100:100] ## s1 vaut "elephant"
s1


Out[17]:
'elephant'

In [18]:
s = "elephant"
s1 = s[100:-100] ## s1 vaut ""
s1


Out[18]:
''

Cette notation peut être utilisée pour palier l'impossibilité de modifier un élément d'une chaine de caractère. Par exemple :


In [19]:
# Insertion d'une lettre en position 4
chaine_1 = "infomatique"
chaine_1 = chaine_1[:4] + "r" + chaine_1[4:]
print( chaine_1 )

# Modification d'une lettre en position 4
chaine_1 = "infolmatique"
chaine_1 = chaine_1[:4] + "r" + chaine_1[5:]
print( chaine_1 )


informatique
informatique

II) Quelques précisions sur les modules

Au démarrage seuls les modules de la librairie standard (The standard Library) sont préinstallés. Un très grand nombre de modules fournis par des tiers, est stoqué dans le Python Package Index. On peut les installer depuis une commande en ligne (pas depuis la console python) à l'aide de diférentes procédures dont la plus polupaire est :

pip install library_name

Parmis les modules que l'on doit absolument connaître dans ce cours nous avons vu math, matplotlib, et d'autre part turtle, ipywidgets ou numpy, ainsi que urllib.request que nous allons voire dans cette seance sont importants, pour votre travail personnel vous pouvez vous servis de pandas mais on peut faire sans.


In [20]:
from math import *
print(pi)


3.141592653589793

Lors de l'importation de vos modules, nous avons vu au moins 3 methodes

1) Importer tout le module

from math import *
print(pi)
#donnera
3.141592653589793

2) Importer les fonctions d'un sous-module du module et le renomer

import matplotlib.pyplot as plt
plt.axes('equal')
plt.show()
# renvoie une fenêtre où les axes ont la même taille
# ici "plt" equivaut à "matplotlib.pyplot"

3) Importer tout (c'est pas toujours la meilleure idée, mais on peux faire...)

import turtle
myPen = turtle.Turtle() #permet d'ouvrir une fenêtre
...
turtle.TK.Scale.rowconfigure(10,0) #change le numero de lignes 
# ici a chaque fois que l'on veut demander une fonction graphique 
# on doit préciser tout le chemin pour y arriver

III) Quelques précisions sur "NONE"

L'objet None est utilisé pour représenter l'absence de d'une valeur. Il est semblable a null dans d'autres langages de programmation. Tout comme d'autre valeurs "vides", tel que 0, [], ou encore la chaine de charactères nulle "", is peut être traduit par le boléen False, si l'on fait une opération de transtypage python.


In [21]:
None == None


Out[21]:
True

In [22]:
None

In [23]:
print(None)


None

Il convient de retennir que None est retourné par toute fonction qui ne devrait pas explicitement rendre quelque chose de particulier, par exemple:


In [24]:
def une_fonction():
    print("Salut les amis !")

une_variable=une_fonction()
print(une_variable)


Salut les amis !
None

In [ ]: