Browse Source

Fin du cours sur les décorateurs

master
Dimitri Merejkowsky 4 years ago
parent
commit
600b2b5f8a
4 changed files with 119 additions and 24 deletions
  1. +2
    -0
      cours/source/06-fonctions-01/02-portée-des-variables.rst
  2. +51
    -4
      cours/source/19-functions-02/01-introduction.rst
  3. +65
    -15
      cours/source/19-functions-02/02-décorateurs.rst
  4. +1
    -5
      cours/source/19-functions-02/index.rst

+ 2
- 0
cours/source/06-fonctions-01/02-portée-des-variables.rst View File

@@ -1,3 +1,5 @@
.. _portées-des-variables:

Portée des variables Portée des variables
==================== ====================




+ 51
- 4
cours/source/19-functions-02/01-introduction.rst View File

@@ -57,7 +57,22 @@ il y a en réalité deux étapes:
1. Python stocke le corps de la fonction quelque part 1. Python stocke le corps de la fonction quelque part
2. Il crée une variable pointant vers ce corps 2. Il crée une variable pointant vers ce corps


En Python, il est assez fréquent d'utiliser de code tel que celui-ci, souvent avec un dictionnaire:
En Python, il est assez fréquent d'utiliser de code tel que celui-ci, souvent avec un dictionnaire::

fonctions_connues = {
"français": dire_bonjour_en_français,
"anglais": dire_bonjour_en_anglais,
}

# Ici on stocke la langue parlée par l'utilisateur
# et son prénom
langue_parlée = ...
prénom = ....

if langue_parlée in fonctions_connues:
fonction = fonctions_connues[langue_parlée]
fonction(prénom)



Fonctions en tant qu'argement d'autres fonctions Fonctions en tant qu'argement d'autres fonctions
------------------------------------------------ ------------------------------------------------
@@ -89,13 +104,41 @@ Fonctions imbriquées


On peut aussi définir une fonction dans une autre fonction:: On peut aussi définir une fonction dans une autre fonction::


TODO

def affiche_message(message):
def affiche():
print(message)

affiche_message("Bonjour")
# affiche: Bonjour

Deux notes importantes:

Premièrement, la fonction `affiche()` qui est imbriquées dans `affiche_message()` n'est pas
accessible à l'éxtérieur de la fonction qui la contient. En d'autres termes, ce code
ne fonctionne pas::

def affiche_message(message):
def affiche():
print(message)

affiche()
# NameError: 'affiche' is not defined

C'est un mécanisme similaire aux :ref:`portées des variables <portées-des-variables>` vu précédemment.

Deuxièment, la fonction `affiche()` à l'intérieur de `affiche_message()`
a accès à l'argument `message` de la fonction `affiche_message`. On appelle
ça une "closure".





Fonctions retournant des fonctions Fonctions retournant des fonctions
---------------------------------- ----------------------------------


Enfin, on peut retourner une fonction depuis une autre fonction::
En réalité, on combine souvent les closures avec des fonctions qui
retournent d'autres fonctions::



def fabrique_fonction_qui_additionne(n): def fabrique_fonction_qui_additionne(n):
def fonction_résultat(x): def fonction_résultat(x):
@@ -114,4 +157,8 @@ Un autre paradigme


Le fait qu'on puisse traiter les fonctions comme n'importe quelle Le fait qu'on puisse traiter les fonctions comme n'importe quelle
autre valeur (c'est-à-dire les assigner à des variables, les passer autre valeur (c'est-à-dire les assigner à des variables, les passer
en argument et les retourner)
en argument et les retourner), est caractéristique des langages
dits "fonctionnels". Python est donc **à la fois** un
langages *impératif*, *objet* et *fonctionnel*. On dit que
c'est un langage *multi-paradigme*.


+ 65
- 15
cours/source/19-functions-02/02-décorateurs.rst View File

@@ -1,23 +1,73 @@
Fonctions en tant qu'argement d'autres fonctions
================================================
Décorateurs
============


On a vu en début de chapitre qu'on peut créé des variables qui pointent
vers des fonctions.
Définition
------------


Du coup, rien n'empêche de les passer en *argument* d'autres fonctions.
Un décorateur est une fonction qui *enveloppe* une autre fonction.


Par exemple::
On place le nom du décorateur avec une arobase (``@``) au-dessus
de la fonction décorée::


def appelle_deux_fois(f):
f()
f()
def mon_décorateur(fonction):
def fonction_retournée():
# fais quelque chose avec fonction
return fonction_retournée


@mon_décorateur
def ma_fonction_décorée(un_argument):
fais_un_truc_avec(un_argument)


def crier():
print("Aline !")
Les deux dernières lignes sont équivalentes à::


appelle_deux_fois(crier)
def ma_fonction_décorée(un_argument):
fais_un_truc_avec(un_argument)


# Affiche:
# Aline !
# Aline !
ma_fonction_décorée = mon_décorateur(ma_fonction_décorée)


Exemples de décorateurs
-----------------------

On peut faire un décorateur qui nous empêche
d'appeler une fonction sous certaines conditions::

def pas_pendant_la_nuit(fonction):
def résultat():
if il_fait_nuit:
print("chut")
else:
fonction()
return résultat

@pas_pendant_la_nuit
def dire_bonjour():
print("bonjour")

il_fait_nuit = True
dire_bonjour()
# afiche: "chut"

Décorateur prenant des arguments
--------------------------------

On peut aussi avoir des arguments passés aux décorateurs. Dans ce cas, on a besoin de
*trois* fonctions imbriquées. En effet, il nous faut une fonction pour traiter l'argument
``message`` et une autre pour traiter l`argument ``fonction``::

def affiche_message_avant_appel(message):
def décorateur(fonction):
def résultat():
print(message)
fonction()
return résultat
return décorateur

@affiche_message_avant_appel("dire_bonjour est appelée")
def dire_bonjour():
print("bonjour")

dire_bonjour()
# affiche:
# dire_bonjour est appelée
# bonjour

+ 1
- 5
cours/source/19-functions-02/index.rst View File

@@ -5,8 +5,4 @@ Chapitre 19 - Décorateurs
:maxdepth: 1 :maxdepth: 1


01-introduction 01-introduction





02-décorateurs