est-ce vraiment utile d’expliquer les affectations (en anglais assignment) ?
étonnamment il y a un million de choses à dire sur les multiples formes de l’affectation !
affectation simple¶
bon à la base c’est simple; cette affectation est une instruction
a = 'alice'
print(a)alice
portée des variables (intermédiaire)¶
pour faire court, la portée d’une variable est la fonction - et non pas, comme dans les langages à la C++, le bloc (c’est d’ailleurs assez cohérent avec le fait qu’il n’y a pas de {} en Python, si on veut)
à savoir également, l’affectation sert aussi de déclaration: si vous affectez une variable dans une fonction, cela signifie que la variable est locale à la fonction
global et nonlocal¶
ces deux mots-clé permettent d’affecter une variable qui justement n’est pas locale à la fonction:global pour référencer une variable globale au module,nonlocal pour référencer une variable dans une fonction imbriquée entre le module et la fonction courante
# exemple avec global
variable = 1
def foo():
global variable
# no worries this time
print(f"inside {variable=}")
variable = 2
print(f"before {variable=}")
foo()
# variable is 2
print(f"outside {variable=}")before variable=1
inside variable=1
outside variable=2
affectation par unpacking¶
une forme très fréquente - et très pratique - d’affectation
on “déballe” le contenu d’une structure, et on affecte les morceaux à plusieurs variables d’un coup
a, b, c = ['alice', 'bob', 'charlie']
print(b)bob
il y a bien sûr quelques contraintes
il faut la même forme à grauche et à droite
mais les types peuvent être différents (tuple à gauche, liste à droite, ..)
extended unpacking¶
on peut utiliser une notation
*devant une (seule) variablecette variable va référencer une liste qui regroupe
tout ce qui n’est pas unpacké dans les autres variablesil ne peut y avoir qu’une seule variable de ce type (sinon ce srait ambigu)
L = [1, 2, 3, 4, 5]a, *b = L
print(f"{a=} {b=}")a=1 b=[2, 3, 4, 5]
a, *b, c, d = L
print(f"{a=} {b=} {c=} {d=}")a=1 b=[2, 3] c=4 d=5
unpacking - ignorer des valeurs avec _¶
lorsqu’on n’est pas intéressé par certaines valeurs il est d’usage d’utiliser la variable
_on peut l’utiliser plusieurs fois - ne pas penser que ça induit une égalité entre, par exemple ici, la 2ème et la 4ème valeur
# je ne garde pas les valeurs à la 2e et 4e position
debut, _, milieu, _, fin = [1, 2, 3, 4, 5]
print(f"{debut=} {fin=} {_=}")debut=1 fin=5 _=4
unpacking et imbrications¶
un peu plus gadget, mais parfois utile:
le terme de gauche peut être imbriqué autant que nécessaire
il faut que les deux termes aient la même forme (pattern-matching)
on peut utiliser indifféremment un tuple ou une liste
# le \ c'est juste pour aligner les deux morceaux
obj = \
1, ( (2, 3), (4, [5, 6])), 6
a, ( _, [b, c ]), d = objprint(f"{a=} {b=} {c=} {d=}")a=1 b=4 c=[5, 6] d=6
affectation multiple¶
ici les variables pointent vers le même objet ! (ça se voit qu’on ne crée qu’une seule liste)
on crée donc une référence partagée
# une seule liste
a = b = c = [1, 2, 3]
a is bTrue# qui donne un résultat très différent de ceci où on crée deux listes
A = [1, 2, 3]
B = [1, 2, 3]
A is BFalse# dans la pratique c'est surtout utilisé en conjonction avec le unpacking
L = car, *cdr = [1, 2, 3]
print(f"{L=} {car=} {cdr=}")L=[1, 2, 3] car=1 cdr=[2, 3]
affectation et boucle for¶
pour anticiper un peu sur les boucles for, l’affectation a lieu aussi à chaque itération de boucle
liste = [1, 10, 100]
for item in liste:
print(f"{item=}", end=" ")item=1 item=10 item=100 # du coup dans un for on peut aussi faire du unpacking
liste = ([1, 2], [10, 20], [100, 200])
for a, b in liste:
print(f"{a=}x{b=}", end=" ")a=1xb=2 a=10xb=20 a=100xb=200 expression d’affectation (walrus)¶
enfin depuis la 3.8 on dispose aussi d’une expression qui fait de l’affectation
bon c’est un peu plus limité que l’instruction (pas de unpacking, pas de seq[i] ou de var.attribut dans la partie gauche)
mais ça rend parfois service:
# exemple 1 : lecture d'un fichier par buffer
CHUNK = 20 * 1024
with open("../data/hamlet.txt") as feed:
while chunk := feed.read(CHUNK):
print(f"[{len(chunk)}]", end='')[20480][20480][20480][20480][20480][20480][20480][20480][15005]# exemple 2 : les regexps
import re
pattern = r"(\d+)(st|nd|rd|th) edition"
with open("../data/hamlet.txt") as feed:
for lineno, line in enumerate(feed, 1):
if match := re.search(pattern, line):
print(match.group(0))3rd edition