
types évolués¶
la liste¶
permet de créer des collections très souples :
séquence d’objets de n’importe quel type
on peut insérer / détruire des objets
pas de contrainte sur la taille
# on crée une liste avec des [ ]
homogene = [0, 12]
homogene
[0, 12]
# on peut mélanger
# les types
heterogene = [2.3, "abc"]
heterogene
[2.3, 'abc']
# des listes dans des listes
groupe = [True, homogene,
"chaine", heterogene]
groupe
[True, [0, 12], 'chaine', [2.3, 'abc']]
type(groupe)
list
groupe
[True, [0, 12], 'chaine', [2.3, 'abc']]
# comme avec les chaines
# on peut accéder au i-ème élément
# les indices commencent à 0
# le premier élément est
# donc le booléen
groupe[0]
True
# on peut remplacer un élément
groupe[1] = '-'
groupe
[True, '-', 'chaine', [2.3, 'abc']]
# et le dernier
groupe[-1]
[2.3, 'abc']
# est heterogene
groupe[-1] == heterogene
True
# le slicing s'applique aussi
# comme sur les chaines de caractère
groupe[::2] # du début à la fin avec un pas de 2
[True, 'chaine']
liste et opérateurs¶
de nombreux opérateurs sont définis aussi sur les listes
# on peut ajouter deux listes,
# ça les concatène
[1, 2, 3] + [4, 5, 6]
[1, 2, 3, 4, 5, 6]
# la comparaison est
# lexicographique
[1, 2, 3] <= [1, 2, 4]
True
# l'opérateur d'appartenance
'chaine' in groupe
True
# et sa négation
'tutu' not in groupe
True
itérations¶
approfondi dans une section ultérieure
mais dans sa forme la plus simple: for .. in .. :
for item in groupe:
print(item)
True
-
chaine
[2.3, 'abc']
listes et performances¶
À savoir
la liste est une structure de données très souple du coup elle n’est que relativement
efficace
elle est surtout optimisée pour être modifiée par la fin
habituellement à base des méthodes append
et pop
tutu = []
# on n'a pas encore vu le for
# mais vous pouvez deviner ce que ça fait
for c in 'abc':
tutu.append(c)
print(tutu)
['a']
['a', 'b']
['a', 'b', 'c']
# et à l'envers
while tutu:
c = tutu.pop()
print(c)
c
b
a
MAIS cela n’est un problème qu’avec des données nombreuses - $10^4$
du coup pour des preuves de concept la liste est TRÈS flexible et pratique
le tuple¶
similaire à la liste, mais qu’on ne peut pas modifier
ne sera pas approfondi dans ce primer
on va voir tout de suite à quoi ça peut bien servir
# ressemble à une liste, mais s'écrit avec des ()
paquet = (12, "abc")
paquet
(12, 'abc')
# on ne peut plus y toucher
# paquet[0] = 15 n'est pas autorisé
# ni paquet.append(0)
l’ensemble¶
une autre forme de container, mais assez différent :
comme pour les ensembles mathématiques, un même élément
ne peut apparaitre qu’une seule fois dans un ensemblela recherche d’un élément dans un ensemble est très efficace
contrairement aux listes, on n’a pas besoin de balayer tous les éléments repose sur la notion de table de hachage - détaillé dans le cours avancépar contre, limitation sur les éléments
certains types ne sont pas éligibles par ex. on ne peut pas mettre une liste dans un ensemble
utiliser à la place untuple
# pour créer un ensemble
ensemble = {12, "abc"}
ensemble
{12, 'abc'}
# méthode add() pour ajouter
ensemble.add(True)
ensemble
{12, True, 'abc'}
# pas de doublon
ensemble.add("abc")
ensemble
{12, True, 'abc'}
# la recherche est rapide
# bien sûr, c'est surtout intéressant
# sur des grosses données
12 in ensemble
True
# on peut mettre un tuple dans un ensemble
ensemble.add((2, 3))
ensemble
{(2, 3), 12, True, 'abc'}
# et pour enlever
ensemble.remove(12)
ensemble
{(2, 3), True, 'abc'}
itérations sur l’ensemble¶
forme la plus simple, idem : for .. in ..
attention qu’un ensemble n’a pas d’ordre naturel
depuis Python-3.7 le parcours se fait dans l’ordre des insertions
for item in ensemble:
print(item)
(2, 3)
True
abc
le dictionnaire¶
aussi un container, mais cette fois c’est conceptuellement
un ensemble d’associations de la forme
clé → valeur
# la syntaxe pour créer
# un dictionnaire en clair
annuaire = {'alice': 25, 'bob': 32}
# les clés sont ici les 2 chaines
# 'alice', 'bob'
annuaire
{'alice': 25, 'bob': 32}
# on ne peut plus accéder par indice
# annuaire[0] ne veut rien dire!
# par contre on peut accéder par clé
annuaire['bob']
32
# pareil pour écrire
# si la clé est inconnue on l'ajoute
annuaire['eve'] = 40
annuaire
{'alice': 25, 'bob': 32, 'eve': 40}
# si la clé existe déjà
# on écrase la valeur associée
annuaire['alice'] = 50
annuaire
{'alice': 50, 'bob': 32, 'eve': 40}
# pour effacer une clé
del annuaire['eve']
annuaire
{'alice': 50, 'bob': 32}
annuaire
{'alice': 50, 'bob': 32}
# la recherche d'une clé est aussi rapide
# que la recherche dans les ensembles
'alice' in annuaire
True
digression : affectation multiple¶
# plutôt que de faire
a = 10
b = 20
print(f"a={a}, b={b}")
a=10, b=20
# on peut faire en Python
a, b = 10, 20
print(f"a={a}, b={b}")
a=10, b=20
dans ce contexte c’est un gadget, mais c’est intéressant parfois
car les termes à droite de =
sont tous évalués avant de faire les affectations
# et ainsi on peut par exemple
# échanger deux variables
a, b = b, a
print(f"a={a}, b={b}")
a=20, b=10
itération sur un dictionnaire¶
même remarque que les ensembles : pas d’ordre naturel
depuis Python-3.7 le parcours se fait dans l’ordre des insertions
for cle, valeur in annuaire.items():
print(f"{cle} → {valeur}")
alice → 50
bob → 32
cette forme est à mettre en rapport avec l’affectation multiple
dans ce sens que ça revient à faire ceci :
# en décomposant un peu pour bien comprendre
for couple in annuaire.items():
cle, valeur = couple # on appelle cela de l'unpacking
print(f"{cle} → {valeur}")
alice → 50
bob → 32
fonctions et arguments multiples (1)¶
mécanisme pour définir un nombre quelconque d’arguments à une fonction
# parfois on a envie qu'une fonction puisse
# accepter un nombre variable d'arguments
def foo(fixe, *variable):
"""
fixe reçoit le premier argument
variable reçoit un tuple avec tous les autres arguments de l'appel
"""
print(f"premier argument: {fixe}")
print(f"les autres: {variable} - de type {type(variable)}")
for item in variable:
print(f"item {item}")
foo(1)
premier argument: 1
les autres: () - de type <class 'tuple'>
foo(1, 2)
premier argument: 1
les autres: (2,) - de type <class 'tuple'>
item 2
foo(1, 2, 3)
premier argument: 1
les autres: (2, 3) - de type <class 'tuple'>
item 2
item 3
bien entendu on ne peut définir qu’un seul paramètre de ce genre, et il doit apparaitre en
dernier dans la signature de la fonction
Si on pouvait en mettre plusieurs, il y aurait ambigüité quant à qui reçoit quoi.
fonctions et arguments multiples (2)¶
dans l’autre sens, si j’ai un container avec des objets que je veux passer individuellement à une fonction
# par exemple j'ai une liste
args = [1, 2, 3]
# et en fait je veux appeler
# foo(1, 2, 3)
#
# je pourrais faire
# foo(args[0], args[1], arg[2])
#
# mais bien sûr ça ne marchera
# que si args contient 3 objets
# dans ce cas on peut utiliser à nouveau
# l'étoile, et faire plutôt
foo(*args)
premier argument: 1
les autres: (2, 3) - de type <class 'tuple'>
item 2
item 3
# vérifions que c'est bien
# ce qu'on voulait
foo(1, 2, 3)
premier argument: 1
les autres: (2, 3) - de type <class 'tuple'>
item 2
item 3
à l’appel de la fonction par contre on peut passer plusieurs arguments étoilés, leurs composants sont simplement ajoutés dans l’ordre aux arguments de la fonction.
résumé¶
Python propose des types prédéfinis
list
: un container flexible et ordonné, accessible par indiceplus accessoirement,
tuple
pour créer des containers similaires mais non modifiablesset
: un container non-ordonné, sans doublon, et à recherche rapidedict
: un ensemble d’associations clé → valeur,
à recherche rapide, accessible par cléla forme
*args
permet aux fonctions d’accepter un nombre quelconque d’argumentsdéfinition
def foo(*args):
appel
foo(*args)