Mettez des fonctions dans vos structures de données


En Python les fonctions sont des objets de premier ordre. On peut les manipuler, copier les références, les supprimer…

Exemple :

# On definit une fonction.
# Jusqu'ici tout va bien...
def pizza():
    return "miam"
 
 
print(pizza())
## miam
 
# On peut assigner la référence de
# la fonction à une variable.
delice = pizza
 
# Et utiliser la fonction depuis la variable
print(delice())
## miam
 
# On peut même supprimer la variable
# originale.
del pizza
print(delice())
## miam
 
pizza()
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-dc0f1f08233f> in <module>()
----> 1 pizza()
 
NameError: name 'pizza' is not defined

La fonction est un objet ordinaire qui peut donc se mettre dans une variable, mais aussi se passer en paramètre, se retourner comme valeur, etc. J’ai déjà expliqué ça dans le tuto sur les décorateurs plus en détail, mais un rappel ne fait pas de mal.

Cela veut dire que l’on peut mettre la référence d’une fonction dans une structure de données.

Par exemple dans une liste :

def pizza():
    return "miam"
 
def epinard():
    return "miam aussi"
 
def arepas():
    return "decidement tout est miam"
 
# On met les fonctions dans la liste :
liste_de_fonctions = [pizza, epinard, arepas]
 
# Et du coup on peut boucler sur les fonctions
for func in liste_de_fonctions:
    print(func())
 
## miam
## miam aussi
## decidement tout est miam
 
# Le monde des listes s'ouvre à vous
 
print(liste_de_fonctions[-1]())
## decidement tout est miam
 
f1, f2 = liste_de_fonctions[:2]
print(f2())
## miam aussi

Mais aussi dans un dictionnaire :

dico_de_fonction = {
    "choix1": pizza,
    "choix2": epinard,
    "choix3": arepas
}
 
print(dico_de_fonction["choix2"]())
## miam aussi
 
for key, func in dico_de_fonction.items():
    print("%s: %s" % (key, func()))
 
## choix1: miam
## choix3: decidement tout est miam
## choix2: miam aussi

En fait, ça marche avec tout (les fonctions sont hashables) : les sets, les tuples, les deques

On peut même faire un générateur qui yield des fonctions :

import random
 
def fonctions_aleatoires(nombre, fonctions=liste_de_fonctions):
    for x in range(nombre):
        yield random.choice(liste_de_fonctions)
 
for func in fonctions_aleatoires(5):
    print(func())
 
## miam aussi
## miam
## decidement tout est miam
## miam
## miam aussi

Python n’a certes pas les capacités de Lisp ou même Javascript pour faire de la programmation fonctionnelle, mais les fonctions restent des objets très puissants dans ce langage.

D’ailleurs, cet article est valable aussi pour les classes et les modules :)

9 thoughts on “Mettez des fonctions dans vos structures de données

  • A. Nonyme

    Merci pour ces exemples !

    J’ai une question qui tue : Est-ce qu’il serait possible de stocker une fonction avec quelques arguments prédéfinis, sans avoir à redéfinir une nouvelle fonction ?

    Exemple qui tue : Je veux stocker un print qui contiendrait déjà certains éléments. Quelque chose qui s’utiliserait comme ça :

    ...
    var1 = "pouet"
    var2 = "prout"
    variable_qui_contient_ma_fonction_print_modifiee(var1, var2)
    >>> Dès fois ça fait prout et dès fois ça fait pouet !

    Est-ce que c’est possible, ou faut obligatoirement créer une nouvelle fonction ?

  • Morgotth

    @A. Nonyme si je comprends bien, tu as besoin de functools.partial, exemple bien d’actualité :

    import functools
    cupidon = functools.partial(print, "Julie Gayet", sep=' + ', end=' = ♥n')
    cupidon('Flanby')
    &gt;&gt;&gt; Julie Gayet + Flanby =

    Sinon pour l’anecdote à 2 francs hors sujet, je suis en train de lire Secrets of the JavaScript Ninja écrit par le créateur de jQuery et le livre revoit tous les points clés du langage avec des cas d’utilisation juste incroyables ! Notamment l’utilisation des fonctions vu dans cet article. UN MUST HAVE ;)

  • Sam Post author

    Pour ceux qui se demandes comment poser une lien proprement en commentaire sur un blog, le commentaire ci-dessus est un bon exemple.

    @A. Nonyme: tu peux suivre l’exemple de Morgoth ou faire une lambda.

    @François : merci !

    @kontre + @foxmask : merci pour l’édition :)

  • Stéphane

    Il y a une erreur dans le deuxième exemple.
    Soit c’est :
    print(pizza)
    ##

    soit c’est :
    print(pizza())
    ## miam

  • Gontran

    @A. Nonyme
    Tu peux faire de l’expension de paramètres.


    l = [
    (lambda x: 2*x, [1]),
    (lambda x,y: 2*x*y, [1,2]),
    ]

    for f in l:
    f[0](*f[1])
    # 2
    # 4

  • furankun

    Etant un joyeux utilisateur de librairies externes genre VTK j’utilisais cette possibilité depuis longtemps. Mais étant un pythonoob je ne m’en étais même pas rendu compte! Merci de m’avoir ouvert un peu plus les yeux, même si ça fait mal le matin.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.