You are here: Sommaire > Plongez au coeur de Python > Le pouvoir de l’introspection > Obtenir des références objet avec getattr | << >> | ||||
Plongez au coeur de PythonDe débutant à expert |
Vous savez déjà que les fonctions Python sont des objets. Ce que vous ne savez pas, c’est que vous pouvez obtenir une référence à une fonction sans connaître son nom avant l’exécution, à l’aide de la fonction getattr.
>>> li = ["Larry", "Curly"] >>> li.pop <built-in method pop of list object at 010DF884> >>> getattr(li, "pop") <built-in method pop of list object at 010DF884> >>> getattr(li, "append")("Moe") >>> li ["Larry", "Curly", "Moe"] >>> getattr({}, "clear") <built-in method clear of dictionary object at 00F113D4> >>> getattr((), "pop") Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'pop'
Ceci retourne une référence à la méthode pop de la liste. Ce n’est pas un appel à la méthode pop, un appel se ferait par li.pop(). C’est la méthode elle-même. | |
Ceci retourne également une référence à la méthode pop, mais cette fois ci le nom de la méthode est passé comme argument de la fonction getattr. getattr est une fonction prédéfinie extrèmement utile qui retourne n’importe quel attribut de n’importe quel objet. Ici, l’objet est une liste et l’attribut est la méthode pop. | |
Au cas où vous ne voyez pas à quel point c’est utile, regardez ceci : la valeur de retour de getattr est la méthode, que vous pouvez alors appeler comme si vous aviez tapé li.append("Moe") directement. Mais vous n’avez pas appelé la fonction directement, vous avez passé le nom de la fonction comme paramètre sous forme de chaîne. | |
getattr fonctionne aussi avec les dictionnaires. | |
En théorie, getattr pourrait fonctionner avec les tuples, mais les tuples n’ont pas de méthodes et getattr déclenchera une exception quel que soit le nom d’attribut que vous lui donnez. |
getattr n’est pas seulement fait pour les types prédéfinis, il fonctionne aussi avec les modules.
>>> import odbchelper >>> odbchelper.buildConnectionString <function buildConnectionString at 00D18DD4> >>> getattr(odbchelper, "buildConnectionString") <function buildConnectionString at 00D18DD4> >>> object = odbchelper >>> method = "buildConnectionString" >>> getattr(object, method) <function buildConnectionString at 00D18DD4> >>> type(getattr(object, method)) <type 'function'> >>> import types >>> type(getattr(object, method)) == types.FunctionType True >>> callable(getattr(object, method)) True
Ceci retourne une référence à la fonction buildConnectionString du module odbchelper, que nous avons étudié au Chapitre 2, Votre premier programme Python. (L’adresse hexadécimale qui s’affiche est spécifique à ma machine, votre sortie sera différente.) | |
A l’aide de getattr, nous pouvons obtenir la même référence à la même fonction. En général, getattr(objet, "attribut") est équivalent à objet.attribut. Si objet est un module, alors attribut peut être toute chose définie dans le module : une fonction, une classe ou une variable globale. | |
Voici ce que nous utilisons dans la fonction info. object est passé en argument à la fonction, method est une chaîne, le nom de la méthode ou de la fonction. | |
Dans ce cas, method est le nom d’une fonction, ce que nous prouvons en obtenant son type. | |
Puisque method est une fonction, elle est callable (appelable). |
Une utilisation usuelle de getattr est dans le rôle de sélecteur. Par exemple, si vous avez un programme qui peut produire des données dans différents formats, vous pouvez définir des fonctions différentes pour chaque format de sortie et utiliser une fonction de sélection pour appeler celle qui convient.
Par exemple, imaginons un programme qui affiche des statistiques de consultations d'un site Web aux formats HTML, XML et texte simple. Le choix du format de sortie peut être spécifié depuis la ligne de commande ou stocké dans un fichier de configuration. Un module statsout définit trois fonctions, output_html, output_xml et output_text. Ensuite, le programme principal définit une fonction de sortie unique, comme ceci :
import statsout def output(data, format="text"): output_function = getattr(statsout, "output_%s" % format) return output_function(data)
Avez vous vu le problème dans l'exemple précédent ? Il y a un couplage très lâche entre chaînes et fonctions et il n'y a aucune vérification d'erreur. Que se passe-t-il si l'utilisateur passe un format pour lequel aucune fonction correspondante n'est définie dans le module statsout? Et bien, getattr retournera None, qui sera assigné à output_function au lieu d'une fonction valide et à la ligne suivante, qui tente d'appeler cette fonction inexistante, plantera et déclenchera une exception. C'est un problème.
Heureusement getattr prend un troisième argument optionnel, une valeurpar défaut.
import statsout def output(data, format="text"): output_function = getattr(statsout, "output_%s" % format, statsout.output_text) return output_function(data)
Comme vous pouvez le voir, getattr est très puissant. C'est le coeur même de l'introspection et vous en verrez des exemples encore plus puissants dans des prochains chapitres.
<< Utilisation de type, str, dir et autres fonction prédéfinies |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
Filtrage de listes >> |