Python: Liste: Difference between revisions

From Wiki Cours
Jump to navigation Jump to search
 
(9 intermediate revisions by the same user not shown)
Line 7: Line 7:
a = list()
a = list()
a = []
a = []
print a # affiche la liste
print(a) # affiche la liste
</source>
</source>
On peut définir une liste en explicitant son contenu, les éléments sont alors séparés par des virgules. Voici un exemple de liste au contenu homogène puis un avec un contenu  
On peut définir une liste en explicitant son contenu, les éléments sont alors séparés par des virgules. Voici un exemple de liste au contenu homogène puis un avec un contenu  
Line 20: Line 20:
<source lang="py">
<source lang="py">
a = [3,2,1,0]
a = [3,2,1,0]
print a[0],a[1],a[2],a[3]
print(a[0],a[1],a[2],a[3])
a[0] = 'a'
a[0] = 'a'
print a
print(a)
</source>
</source>
À cet usage proche des langages de bas niveaux, Python offre des fonctions puissantes de 'slicing' (découpage) des indices qui permettent d'accéder facilement à un ou des éléments en particulier. Voici quelques exemples à essayer qui permettent de comprendre les mécanismes
À cet usage proche des langages de bas niveaux, Python offre des fonctions puissantes de 'slicing' (découpage) des indices qui permettent d'accéder facilement à un ou des éléments en particulier. Voici quelques exemples à essayer qui permettent de comprendre les mécanismes
<source lang="py">
<source lang="py">
a = range(10) # listes des entiers de 0 à 9
a = list(range(10)) # listes des entiers de 0 à 9
              # en Python 2, la fonction range() renvoie une liste, pas besoin de mettre list()
              # en Python 3, elle renvoie un itérateur à partir duquel on crée une liste avec list()
a[-1]        # dernier élément du tableau,  
a[-1]        # dernier élément du tableau,  
               # a[-i] équivaut à a[len(a)-i] sauf pour i=0
               # a[-i] équivaut à a[len(a)-i] sauf pour i=0
Line 57: Line 59:
b = a
b = a
b[2] = 5
b[2] = 5
print a,b
print(a,b)
</source>
</source>
Pour réellement créer une copie indépendante, il faut générer une nouvelle liste en dupliquant le contenu de a. Il y a deux façons simple de le faire: avec l'initialisateur '''list()''' ou l'indiçage du contenu en entier via l'opération [:]
Pour réellement créer une copie indépendante, il faut générer une nouvelle liste en dupliquant le contenu de a. Il y a deux façons simple de le faire: avec l'initialisateur '''list()''' ou l'indiçage du contenu en entier via l'opération [:]
Line 66: Line 68:
c = a[:]
c = a[:]
c[1] = -3
c[1] = -3
print a,b,c
print(a,b,c)
</source>
</source>
En fait, il reste cependant un problème dans le cas où la liste contient des éléments qui sont des objets plus compliqués que les types de base (entiers, réels,...), en particulier des listes. Regardons en effet le résultat d'une copie d'une liste de listes:
En fait, il reste cependant un problème dans le cas où la liste contient des éléments qui sont des objets plus compliqués que les types de base (entiers, réels,...), en particulier des listes. Regardons en effet le résultat d'une copie d'une liste de listes:
Line 73: Line 75:
b = list(a)
b = list(a)
b[2][0] = 5
b[2][0] = 5
print a,b
print(a,b)
</source>
</source>
On voit que le contenu de a a été modifié car la copie a copié comme nouvel élément de b l'adresse de la liste élément de a. Pour effectuer une copie complète du contenu à tous les niveaux, Python offre une fonction '''deepcopy''' présente dans la bibliothèque '''copy''' du standard.  Refaire alors
On voit que le contenu de a a été modifié car la copie a copié comme nouvel élément de b l'adresse de la liste élément de a. Pour effectuer une copie complète du contenu à tous les niveaux, Python offre une fonction '''deepcopy''' présente dans la bibliothèque '''copy''' du standard.  Refaire alors
Line 81: Line 83:
b = deepcopy(a)
b = deepcopy(a)
b[2][0] = 5
b[2][0] = 5
print a,b
print(a,b)
</source>
</source>
Noter que cette bibliothèque offre également une fonction '''copy''' qui fait la même chose qu'avec '''list()''' mais avec un nom plus évocatif et il s'agit surtout d'une méthode plus générique et ré-définissable pour des objets plus complexes.
Noter que cette bibliothèque offre également une fonction '''copy''' qui fait la même chose qu'avec '''list()''' mais avec un nom plus évocatif et il s'agit surtout d'une méthode plus générique et ré-définissable pour des objets plus complexes.
Line 97: Line 99:
N = 5
N = 5
# addition de liste '+', rajoute un élément ou fusionne deux listes (l'ordre compte)
# addition de liste '+', rajoute un élément ou fusionne deux listes (l'ordre compte)
print [1,2] + [3,4,5],  [3,4,5] + [1,2]  
print([1,2] + [3,4,5],  [3,4,5] + [1,2])
# opérateur multiplier '*' répète N fois l'addition:
# opérateur multiplier '*' répète N fois l'addition:
print [1]*N
print( [1]*N )
# vous pouvez combiner ces opérations pour obtenir des structures complexes dès l'initialisation
# vous pouvez combiner ces opérations pour obtenir des structures complexes dès l'initialisation
print ([ [2,3] ]*2 + ['a'])*3
print( ([ [2,3] ]*2 + ['a'])*3 )


# On peut ajouter un élément avec l'addition ou bien la méthode '''append()'''
# On peut ajouter un élément avec l'addition ou bien la méthode '''append()'''
Line 109: Line 111:


# utilisation de la fonction range().
# utilisation de la fonction range().
# range(n) : entiers depuis 0 jusqu'à n-1
# range(n) : itérateur sur les entiers depuis 0 jusqu'à n-1
# range(start,stop,step) : entiers depuis start à stop par saut de step
# range(start,stop,step) : parcourt l'intervalle [start,stop-1] par saut de step
print range(10)
print(list(range(10)))
print range(-10,10,2)
print(list(range(-10,10,2)))
 
</source>
</source>


Line 144: Line 145:
# En l'absence de 'ind', le dernier élément est enlevé.
# En l'absence de 'ind', le dernier élément est enlevé.
a.pop(ind)
a.pop(ind)
print a.pop(), a
print(a.pop(), a)


# Indice d'un élément 'e' sur le domaine d'indices [start,stop].
# Indice d'un élément 'e' sur le domaine d'indices [start,stop].
Line 156: Line 157:
# tri de la liste (message d'erreur si les éléments ne sont pas comparables)
# tri de la liste (message d'erreur si les éléments ne sont pas comparables)
a.sort()
a.sort()
print sorted(a)
print(sorted(a))


# comptage du nombre d’occurrence de l'élément 'e' à l'intérieur de la liste
# comptage du nombre d’occurrence de l'élément 'e' à l'intérieur de la liste
Line 181: Line 182:
# seulement y accéder en lecture
# seulement y accéder en lecture
for e in a:
for e in a:
     print e # on peut utiliser l'information dans e pour faire un calcul
     print(e) # on peut utiliser l'information dans e pour faire un calcul
     e = 0.0
     e = 0.0
print a # n'a pas été modifiée
print(a) # n'a pas été modifiée


# enfin, on peut extraire à la fois le couple (tuple) indice/élément
# enfin, on peut extraire à la fois le couple (tuple) indice/élément
Line 189: Line 190:


for index,elem in enumerate(a):
for index,elem in enumerate(a):
     print index, elem
     print(index, elem)


</source>
</source>
Line 202: Line 203:
sum(a)
sum(a)
map(f,a) # applique la fonction f() aux éléments de a
map(f,a) # applique la fonction f() aux éléments de a
filter(test,a) # crée une liste dont les éléments retournent True si
        # map() en Python 3 renvoie un itérateur
list(map(f,a)) # pour créer une liste contenant f(a)
filter(test,a) # renvoie un itérateur dont les éléments retournent True si
               # la fonction test(t) leur est appliquée, rien sinon
               # la fonction test(t) leur est appliquée, rien sinon
filter(lambda x: x%2,a)    # renvoie les  nombres impairs
              # rajouter list(...) si vous voulez créer une liste
filter(lambda x: not x%2,a) # renvoie les  nombres pairs
list(filter(lambda x: x%2,a))    # renvoie les  nombres impairs
list(filter(lambda x: not x%2,a)) # renvoie les  nombres pairs
 
for i in zip(range(10),range(10,20)): # permet de parcourir des listes en parallèle
    print(i)                          # renvoie un tuple sur les éléments de même indice
                                      # on peut passer plus de deux listes en argument
                                      # zip(a,b,c,d,...)
</source>
</source>


Line 216: Line 225:
</source>
</source>
On prendra garde que les méthodes de slicing ne sont pas toujours intuitives dans la syntaxe. À l'usage, on préfèrera l'utilisation de librairies d'algèbre linéaire comme '''numpy''' et les objets type '''ndarray'''.
On prendra garde que les méthodes de slicing ne sont pas toujours intuitives dans la syntaxe. À l'usage, on préfèrera l'utilisation de librairies d'algèbre linéaire comme '''numpy''' et les objets type '''ndarray'''.
De plus, l'initialisation avec l'opérateur '''*''' pour les listes n'a pas un comportement intuitif, préférer les initialisations avec la compréhension des listes. Regarder par exemple :
<source lang="py">
L = 3
m = [ [0]*L ]*L  # utilise une copie multiple de la meme liste                                                                                                                                                                               
for i in range(L):
    for j in range(L):
        m[i][j] = i+j
print(m)
m = [ [0 for i in range(L)] for j in range(L) ]
for i in range(L):
    for j in range(L):
        m[i][j] = i+j
print(m)
m = list()
for i in range(L):
    m.append([ i+j  for j in range(L)])
print(m)
</source>

Latest revision as of 11:22, 7 November 2016

<--Sommaire

Initialisation

Une liste est un tableau ordonné qui contient des pointeurs vers des objets qui peuvent être simplement des données numériques (entiers ou réels) ou des choses plus compliquées comme des nombres complexes ou même des listes. Pour créer une liste vide, on peut faire

a = list()
a = []
print(a) # affiche la liste

On peut définir une liste en explicitant son contenu, les éléments sont alors séparés par des virgules. Voici un exemple de liste au contenu homogène puis un avec un contenu

a = [1,4,2,3] # une liste d'entiers
a = [ 2, complex(1,3), 4.5, ['a','b','c'] ] # une liste au contenu inhomogène

Indexage

On accède aux éléments de la liste à l'aide de l'opérateur d'indiçage [] comme en C. De même qu'en C, le premier indice est 0. Cet opérateur permet à la fois d'accéder au contenu stocké à la ième place, via a[i], mais aussi de le modifier.

a = [3,2,1,0]
print(a[0],a[1],a[2],a[3])
a[0] = 'a'
print(a)

À cet usage proche des langages de bas niveaux, Python offre des fonctions puissantes de 'slicing' (découpage) des indices qui permettent d'accéder facilement à un ou des éléments en particulier. Voici quelques exemples à essayer qui permettent de comprendre les mécanismes

a = list(range(10)) # listes des entiers de 0 à 9
              # en Python 2, la fonction range() renvoie une liste, pas besoin de mettre list()
              # en Python 3, elle renvoie un itérateur à partir duquel on crée une liste avec list()
a[-1]         # dernier élément du tableau, 
              # a[-i] équivaut à a[len(a)-i] sauf pour i=0
a[2:]         # affiche tous les éléments à partir du 2ème
a[:5]         # affiche tous les éléments jusqu'au 5ème
a[start:stop] # affiche tous les éléments d'indices entre start et (stop-1)
a[start:stop:step] # affiche tous les éléments d'indices entre start et (stop-1) par saut de 'step'
a[1:10:2]     # les entiers impaires
# et vous pouvez jouer en combinant les astuces...
a[-9:-2:3]
# attention cependant, on pourrait croire que l'on peut mettre à zéro
# tout ou partie des éléments d'une liste avec les commandes
a[:] = 0
a[0:10:2] = 0
# mais cela n'est pas possible car les membres de gauche sont dans ce cas des listes
# la solution est alors de parcourir la liste ou bien d'affecter une autre liste membre à membre
a[0:10:2] = [0.0]*len(a[0:10:2])

Copie d'une liste

Il faut faire attention au fait qu'en Python, qui a un typage dynamique, l'affection suivante fait que la liste b va pointer vers le contenu de a:

a = [3,2,1,0]
b = a

Si l'on modifie un élément de b, le contenu est changé et donc les éléments de a également

a = [3,2,1,0]
b = a
b[2] = 5
print(a,b)

Pour réellement créer une copie indépendante, il faut générer une nouvelle liste en dupliquant le contenu de a. Il y a deux façons simple de le faire: avec l'initialisateur list() ou l'indiçage du contenu en entier via l'opération [:]

a = [3,2,1,0]
b = list(a)
b[2] = 5
c = a[:]
c[1] = -3
print(a,b,c)

En fait, il reste cependant un problème dans le cas où la liste contient des éléments qui sont des objets plus compliqués que les types de base (entiers, réels,...), en particulier des listes. Regardons en effet le résultat d'une copie d'une liste de listes:

a = [ [2,3] for i in range(4) ]
b = list(a)
b[2][0] = 5
print(a,b)

On voit que le contenu de a a été modifié car la copie a copié comme nouvel élément de b l'adresse de la liste élément de a. Pour effectuer une copie complète du contenu à tous les niveaux, Python offre une fonction deepcopy présente dans la bibliothèque copy du standard. Refaire alors

from copy import deepcopy
a = [ [2,3] for i in range(4) ]
b = deepcopy(a)
b[2][0] = 5
print(a,b)

Noter que cette bibliothèque offre également une fonction copy qui fait la même chose qu'avec list() mais avec un nom plus évocatif et il s'agit surtout d'une méthode plus générique et ré-définissable pour des objets plus complexes.

from copy import copy
a = [ [2,3] for i in range(4) ]
b = copy(a)
...

Génération de listes

Un des points forts de Python est la possibilité de générer et modifier efficacement des listes. Vous pouvez étudier les exemples suivants

N = 5
# addition de liste '+', rajoute un élément ou fusionne deux listes (l'ordre compte)
print([1,2] + [3,4,5],  [3,4,5] + [1,2])
# opérateur multiplier '*' répète N fois l'addition:
print( [1]*N )
# vous pouvez combiner ces opérations pour obtenir des structures complexes dès l'initialisation
print( ([ [2,3] ]*2 + ['a'])*3 )

# On peut ajouter un élément avec l'addition ou bien la méthode '''append()'''
a = [ 0 ]*4
a += [1]  # ne pas oublier les crochets ici car il faut ajouter une liste de 1 élément.
a.append(1) # plus efficace, l'argument de append étant l'élément à ajouter, pas de crochets ici.

# utilisation de la fonction range().
# range(n) : itérateur sur les entiers depuis 0 jusqu'à n-1
# range(start,stop,step) : parcourt l'intervalle [start,stop-1] par saut de step
print(list(range(10)))
print(list(range(-10,10,2)))

Méthodes utiles pour les listes

# nombre d'éléments
len(a)

# Ajout d'un élément 'e' à la fin de la liste.
# plus efficace que l'addition de liste
a.append(e)

# Insertion de l'élément 'e' à l'indice 'ind'. Si l'indice est supérieur à 
# la taille de la liste, l'élément est mis à la fin
a.insert(ind,e)

# Destruction du ième élément, ou même d'une série correspondant
# à un découpage des indices
del a[i]
del a[2:5]  # détruit les éléments d'indices 2 à 4

# Elimination de l'élément 'e' en le recherchant à partir de la fin 
# (message d'erreur si l'élément n'est pas dans la liste)
a.remove(e)
a.remove(a[-1]) # enlève le dernier élément
a.remove(a[0])  # enlève le premier élément sauf s'il apparaît plus tard dans la liste

# Elimination de l'élément d'indice 'ind' et renvoie de la valeur enlevée. 
# En l'absence de 'ind', le dernier élément est enlevé.
a.pop(ind)
print(a.pop(), a)

# Indice d'un élément 'e' sur le domaine d'indices [start,stop].
# Retourne l'indice du premier élément rencontré en partant de la gauche. 
# Par défaut, start est 0 et stop est le dernier indice
a.index(e,start,stop)

# Inversion de l'ordre des éléments
a.reverse()

# tri de la liste (message d'erreur si les éléments ne sont pas comparables)
a.sort()
print(sorted(a))

# comptage du nombre d’occurrence de l'élément 'e' à l'intérieur de la liste
a.count(e)

Parcourir une liste

Il existe plusieurs façon plus ou moins concise et intuitive de parcourir une liste, par des procédés qui sont parfois communs à d'autres conteneurs.

# la solution la plus courante en utilisant range() et len() pour générer la liste des indices
for i in range(len(a)):
    a[i] = 0.0

# on peut générer une liste d'indices pour ne travailler que sur 
# une partie des éléments
indices_pairs = range(len(a))[0:len(a):2]
for i in indices_pairs:
    a[i] = 0.0

# on peut aussi utiliser directement un pointeur sur les éléments de a
# mais on ne pourra dans ce cas pas modifier le contenu de l'élément,
# seulement y accéder en lecture
for e in a:
    print(e) # on peut utiliser l'information dans e pour faire un calcul
    e = 0.0
print(a) # n'a pas été modifiée

# enfin, on peut extraire à la fois le couple (tuple) indice/élément
# en utiliser la fonction enumerate()

for index,elem in enumerate(a):
    print(index, elem)

Quelques fonction utiles

La fonction est évidente si aucune précision n'est donnée

a = [1,4,6,2,3,10]
max(a)
min(a)
sum(a)
map(f,a) # applique la fonction f() aux éléments de a
         # map() en Python 3 renvoie un itérateur
list(map(f,a)) # pour créer une liste contenant f(a)
filter(test,a) # renvoie un itérateur dont les éléments retournent True si
               # la fonction test(t) leur est appliquée, rien sinon
               # rajouter list(...) si vous voulez créer une liste
list(filter(lambda x: x%2,a))     # renvoie les  nombres impairs
list(filter(lambda x: not x%2,a)) # renvoie les  nombres pairs

for i in zip(range(10),range(10,20)): # permet de parcourir des listes en parallèle
    print(i)                          # renvoie un tuple sur les éléments de même indice
                                      # on peut passer plus de deux listes en argument
                                      # zip(a,b,c,d,...)

Tableaux multidimensionnels

Il est relativement facile de créer des tableaux multidimensionnels avec des listes de listes:

mat = [ [1,2,3], [3,2,1], [1,1,2] ]
mat[0][1]  # accès aux éléments i,j

On prendra garde que les méthodes de slicing ne sont pas toujours intuitives dans la syntaxe. À l'usage, on préfèrera l'utilisation de librairies d'algèbre linéaire comme numpy et les objets type ndarray.

De plus, l'initialisation avec l'opérateur * pour les listes n'a pas un comportement intuitif, préférer les initialisations avec la compréhension des listes. Regarder par exemple :

L = 3

m = [ [0]*L ]*L  # utilise une copie multiple de la meme liste                                                                                                                                                                                 
for i in range(L):
    for j in range(L):
        m[i][j] = i+j
print(m)

m = [ [0 for i in range(L)] for j in range(L) ]
for i in range(L):
    for j in range(L):
        m[i][j] = i+j
print(m)

m = list()
for i in range(L):
    m.append([ i+j  for j in range(L)])
print(m)