FORMATION PYTHON

Formation Python

Année 2023

_

FORMATION PYTHON

Closure ou fermeture

La mise en oeuvre de cette technique nous oblige à étudier la portée des variables en python à travers les scopes.

Notions de scope

En python, il existe 2 scopes:

  • global, créé au lancement de l'interpreteur Python et qui existe le temps de l'exécution de l'interpréteur Python
  • local, nouvellement créé à chaque appel de fonction, et qui existe le temps de l'exécution de la fonction

Le scope global est accessible, depuis n'importe quelle partie du programme, via la fonction interne globals()

Le scope local est disponible depuis la fonction en cours d'exécution via la fonction interne locals(). Il contient à la fois les paramètres de la fonction, les variables et fonctions locales, les classes, tout ce qui a été défini dans la fonction

Quand une variable ou une fonction n'est pas definie dans le scope local, on recherche au niveau du scope local appelant.

FORMATION PYTHON

Par exemple:

msg_mr = "Mr"

def fct(val1):
	# ici lors de l'exécution de la fonction **test**, *msg_mr* sera recherché dans le scope
	# de fct. Idem pour msg_mme

	print(msg_mr)

	msg_mme = 'Mme'

	def test(val2):
		"""Ici `msg_mme` n'étant pas defini dans la fonction **test**
		"""
		print(msg_mme)

		# ici val1 est défini dans le scope de l'appelant
		# pareil pour msg
		print(f'voici {val1} + {val2} => {msg}')

	# ici msg est utilisé dans la fonction test
	msg = 'hello'
	test(10)

fct('Yves')
FORMATION PYTHON

La closure

Cela consiste à conserver les variables d'un scope local par l'intermédiaire d'une fonction interne qui est renvoyée comme valeur de retour. Voici un exemple:

from typing import Callable

def caractere_ref(char: str) -> Callable[[str, int], str]:
 	"""
 	"""
 	def remplir_avec(ma_chaine: str, largeur: int=60) -> str:
 		# maj du compteur d'appel
 		remplir_avec.cpt += 1

 		#do the job
 		return ma_chaine.center(largeur, char)

 	# affectation d'un attribut `cpt` à la fonction
 	remplir_avec.cpt = 0

 	return remplir_avec

Dans ce cas, le paramètre char de la fonction caractere_ref est conservé lorsque la fonction remplir_avec est renvoyée. Il est utilisé dans cette fonction lors du formatage de la chaine. De plus à cette fonction, est ajouté dynamiquement un attribut cpt. Celcui-ci permettra de compter le nombre d'appel à la fonction remplir_avec pour chaque instance créée à partir de caractere_ref.

FORMATION PYTHON

Mise en oeuvre

A partir de la fermeture définit précédemment, voici 2 exemples:

car_plus = caractere_ref('+')
print(car_plus)
car_under = caractere_ref('_')
print(car_under)

print(car_plus('hello'))
print(car_plus.cpt)
for i in range(5):
	print(car_under(f'{i}{i}', 80))
print(car_under.cpt)

En savoir plus

(Scopes, closures et référencement) [https://zestedesavoir.com/tutoriels/3163/variables-scopes-et-closures-en-python/#2-referencement-et-dereferencement]

(Les closures)[https://www.it-swarm-fr.com/fr/python/pourquoi-les-fonctions-imbriquees-dans-python-ne-sappellent-elles-pas-des-fermetures/970701931/]

Attention: dans ce dezrnier article, func_closure doit être remplacée par __closure__ en python3.