Qu’est-ce qu’un callable en Python ?


Petit définition du jour.

Un callable, qu’on peut traduire maladroitement par “appelable”, est un objet qui peut être appelé. Et ça ne vous arrange pas beaucoup de savoir ça.

On parle de callable dans les tutos, les docs, etc, en supposant que vous savez ce que ça veut dire.

En fait c’est très simple, si vous pouvez mettre deux parenthèses après le nom d’un objet (en fait de la variable qui contient l’objet, mais ne chipotons pas) pour obtenir un effet, alors l’objet est un callable.

Une fonction est un callable:

>>> def fonction():
...     print("Vous m'avez appelé")
...
>>> fonction() # appel de la fonction
Vous m'avez appelé

Une classe est un callable:

>>> Class() # appel de la classe
<__main__.Class object at 0x26d8310>

Une méthode est un callable :

>>> class Class(object):
def methode(self):
print("Veuillez patientez, nous allons répondre à votre appel")
...
>>> obj = Class()
>>> obj.methode() # appel de la méthode
Veuillez patientez, nous allons répondre à votre appel

Il sont callables car on peut faire () dessus, et il se passe quelque chose. On peut les appeler.

Et par voie de conséquence, un callable peut retourner une valeur quand il est appelé. En fait, un callable est même garanti de retourner une valeur quand il est appelé, puisque toute fonction ou méthode retourne None par défaut en Python, et toute classe retourne au moins un objet vide.

Les string, les int, les listes, les fichiers ou les dicos ne sont pas des callables :

>>> 1()
Traceback (most recent call last):
File "<ipython-input-11-769e123a5ede>", line 1, in <module>
1()
TypeError: 'int' object is not callable
 
>>> ""()
Traceback (most recent call last):
File "<ipython-input-12-de235e3e26d7>", line 1, in <module>
""()
TypeError: 'unicode' object is not callable
 
>>> []()
Traceback (most recent call last):
File "<ipython-input-13-bda5b10b5bf7>", line 1, in <module>
[]()
TypeError: 'list' object is not callable
 
>>> {}()
Traceback (most recent call last):
File "<ipython-input-14-67901a4bc3e8>", line 1, in <module>
{}()
TypeError: 'dict' object is not callable
 
>>> f = open('/etc/fstab')
>>> f()
Traceback (most recent call last):
File "<ipython-input-16-0ec059b9bfe1>", line 1, in <module>
f()
TypeError: 'file' object is not callable

Mais les classes (et oui, ce sont des classes, pas des fonctions malgré leurs noms en minuscule) str, int, list, dict et file sont des callables :

>>> int()
0
>>> str()
''
>>> dict()
{}
>>> list()
[]
>>> file('/etc/fstab')
<open file u'/etc/fstab', mode 'r' at 0x2689930>

En fait, la plupart des objets ne sont tout simplement pas des callables. Aucun nouvel objet n’est un callable par nature.

>>> obj = Class()
 
>>> obj()
Traceback (most recent call last):
File "<ipython-input-18-da8742d08647>", line 1, in <module>
obj()
TypeError: 'Class' object is not callable

Donc, quand on vous dit de passer un “callable” en paramètre, généralement on vous dit de passer une fonction (sans les parenthèses), une classe (sans les parenthèses) ou une méthode (sans les parenthèses), afin de s’en servir comme callback.

Par exemple, les champs des modèles Django acceptent un callable comme paramètre par défaut. Comme les callables sont garantis de retourner une valeur, Django utilise cela pour créer dynamiquement une valeur par défaut. La fonction sort() des listes accepte un callable en callback pour le paramètre key.

Demander un callable, c’est donc demander un truc qu’on peut appeler en utilisant des parenthèses, et qui va retourner un autre truc.

Au passage, pour votre culture, on peut créer ses propres callables. Ça sert rarement, dans quelques cas tordus. Il suffit de créer une classe avec la méthode magique __call__, et l’objet retourné sera automatiquement un callable :

>>> class CreerUnCallable(object):
...         def __call__(self):
...                 return "Vous m'avez appelé, maître ?"
...
>>> un_callable = CreerUnCallable()
>>> print(un_callable())
Vous m'avez appelé, maître ?

On a donc ici DEUX callables : la classe, qui est callable par nature, et l’instance de la classe, qui est callable grâce à la méthode __call__.

Et moi j’ai commencé à taper cet article parce que je me suis dit que c’était une notion simple et que ça allait être vite fait, juste avant le petit dèj. Ca fait une heure que je suis dessus. Qu’est-ce que je suis con des fois.

8 thoughts on “Qu’est-ce qu’un callable en Python ?

  • Réchèr

    Loi d’Hofstadter : il faut toujours plus de temps que prévu pour faire un truc, même en tenant compte de la loi d’Hofstadter.

    Voilà pourquoi tu as pris ton petit dèj’ à l’heure de l’apéro.

  • G-rom

    Et quand une put*** de function veut un callable et qu’on n’a qu’une valeur, bin on fait une lambda qui renvoie la valeur et un gros fuck.

  • Sam Post author

    @Recher: je croyais que c’étais la loi de parkinson.

    @Lezy: imgur, imposetonanonymat, bing image, google image…

  • Luigi

    Effectivement, un certain nombre d’imposetonanonymat dernièrement :o)

  • foxmask

    ya qu’un guss qui s’est intéressé au contenu du billet sur 6 commentaires ; zetes pas cool :P

Comments are closed.

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