4.8. Assembler les pièces

La dernière ligne du code, la seule que nous n’ayons pas encore déconstruite, est celle qui fait tout le travail. Mais arrivé à ce point, le travail est simple puisque tous les éléments dont nous avons besoin sont disponibles. Les dominos sont en place, il ne reste qu’à les faire tomber.

Voici le plat de résistance de apihelper.py:

    print "\n".join(["%s %s" %
                      (method.ljust(spacing),
                       processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])

Notez que ce n’est qu’une commande, répartie sur plusieurs lignes sans utiliser le caractère de continuation («\»). Vous vous rappelez quand j’ai dit que certaines expressions peuvent être divisées en plusieurs lignes sans utiliser de backslash ? Une list comprehension est une expression de ce type car toute l’expression est entourée de crochets.

Maintenant étudions l’expression de la fin vers le début. L'instruction

      for method in methodList

nous montre qu’il s’agit d’une list comprehension. Comme vous le savez, methodList est une liste de toutes les méthodes qui nous intéressent dans object. Nous parcourons donc cette liste avec method.

Exemple 4.22. Obtenir une docstring dynamiquement

>>> import odbchelper
>>> object = odbchelper                   1
>>> method = 'buildConnectionString'      2
>>> getattr(object, method)               3
<function buildConnectionString at 010D6D74>
>>> print getattr(object, method).__doc__ 4
Build a connection string from a dictionary of parameters.

    Returns string.
1 Dans la fonction info, object est l’objet pour lequel nous demandons de l’aide, passé en argument.
2 Pendant que nous parcourons la methodList, method est le nom de la méthode en cours.
3 En utlisant la fonction getattr, nous obtenons une référence à la fonction method du module object.
4 Maintenant, afficher la docstring de la méthode est facile.

La pièce suivante du puzzle est l’utilisation de str sur la docstring. Comme vous vous rappelez peut-être, str est une fonction prédéfinie pour convertir des données en chaîne. Mais une docstring est toujours une chaîne, alors pourquoi utiliser str ? La réponse est que toutes les fonctions n’ont pas de docstring, et que l’attribut __doc__ de celles qui n’en ont pas renvoi None.

Exemple 4.23. Pourquoi utiliser str sur une docstring ?

>>> >>> def foo(): print 2
>>> >>> foo()
2
>>> >>> foo.__doc__     1
>>> foo.__doc__ == None 2
True
>>> str(foo.__doc__)    3
'None'
1 Nous pouvons facilement définir une fonction qui n’a pas de docstring, sont attribut __doc__ est None. Attention, si vous évaluez directement l’attribut __doc__, l'IDE Python n’affiche rien du tout, ce qui est logique si vous y réflechissez mais n’est pas très utile.
2 Vous pouvez vérifier que la valeur de l’attribut __doc__ est bien None en faisant directement la comparaison.
3 Lorsque l’on utilise la fonction str, elle prend la valeur nulle et en retourne une représentation en chaîne, 'None'.
NOTE
En SQL, vous devez utiliser IS NULLmethod au lieu de = NULL pour la comparaison d’une valeur nulle. En Python, vous pouvez utiliser aussi bien == None que is None, mais is None est plus rapide.

Maintenant que nous sommes sûrs d’obtenir une chaîne, nous pouvons passer la chaîne à processFunc, que nous avons déjà défini comme une fonction qui replie ou non les espace. Maintenant vous voyez qu’il était important d’utiliser str pour convertir une valeur None en une représentation en chaîne. processFunc attend une chaîne comme argument et appelle sa méthode split, ce qui échouerait si nous passions None, car None n’a pas de méthode split.

En remontant en arrière encore plus loin, nous voyons que nous utilisons encore le formatage de chaîne pour concaténer la valeur de retour de processFunc avec celle de la méthode ljust de method. C’est une nouvelle méthode de chaîne que nous n’avons pas encore rencontré.

Exemple 4.24. Présentation de la méthode ljust

>>> s = 'buildConnectionString'
>>> s.ljust(30) 1
'buildConnectionString         '
>>> s.ljust(20) 2
'buildConnectionString'
1 ljust complète la chaîne avec des espaces jusqu’à la longueur donnée. La fonction info l’utilise pour afficher sur deux colonnes et aligner les docstring de la seconde colonne.
2 Si la longueur donnée est plus petite que la longueur de la chaîne, ljust retourne simplement la chaîne sans la changer. Elle ne tronque jamais la chaîne.

Nous avons presque terminé. Ayant obtenu le nom de méthode complété d’espaces de la méthode ljust et la docstring (éventuellement repliée sur une ligne) de l’appel à processFunc, nous concaténons les deux pour obtenir une seule chaîne. Comme nous faisons une mutation de methodList, nous obtenons une liste de chaînes. En utlisant la méthode join de la chaîne "\n", nous joignons cette liste en une chaîne unique, avec chaque élément sur une ligne et affichons le résultat..

Exemple 4.25. Affichage d’une liste

>>> li = ['a', 'b', 'c']
>>> print "\n".join(li) 1
a
b
c
1 C’est aussi une astuce de débogage utile lorsque vous travaillez avec des liste. Et en Python, vous travaillez toujours avec des listes.

C’est la dernière pièce du puzzle. Le code devrait maintenant être parfaitement compréhensible.

    print "\n".join(["%s %s" %
                      (method.ljust(spacing),
                       processFunc(str(getattr(object, method).__doc__)))
                     for method in methodList])