You are here: Sommaire > Plongez au coeur de Python > Fonctions dynamiques > plural.py, étape 4 | << >> | ||||
Plongez au coeur de PythonDe débutant à expert |
Nous allons extraire la duplication de code pour rendre plus facile la définition de nouvelles règles.
import re def buildMatchAndApplyFunctions((pattern, search, replace)): matchFunction = lambda word: re.search(pattern, word) applyFunction = lambda word: re.sub(search, replace, word) return (matchFunction, applyFunction)
Si cela semble totalement confus (et ça l'est certainement, c'est très inhabituel), la manière dont cette fonction est utilisée devrait éclaircir ces définitions.
patterns = \ ( ('[sxz]$', '$', 'es'), ('[^aeioudgkprt]h$', '$', 'es'), ('(qu|[^aeiou])y$', 'y$', 'ies'), ('$', '$', 's') ) rules = map(buildMatchAndApplyFunctions, patterns)
Je vous assure que c'est vrai : rules contient exactement la même liste de fonction que dans la version précédente. Déplions la définition de rules, nous obtenons ce qui suit :
rules = \ ( ( lambda word: re.search('[sxz]$', word), lambda word: re.sub('$', 'es', word) ), ( lambda word: re.search('[^aeioudgkprt]h$', word), lambda word: re.sub('$', 'es', word) ), ( lambda word: re.search('[^aeiou]y$', word), lambda word: re.sub('y$', 'ies', word) ), ( lambda word: re.search('$', word), lambda word: re.sub('$', 's', word) ) )
def plural(noun): for matchesRule, applyRule in rules: if matchesRule(noun): return applyRule(noun)
Puisque la liste rules est la même que dans la version précédente, il n'est pas étonnant que la fonction plural ne soit pas modifiée. Rappelez-vous qu'elle est totalement générique, elle prend une liste de fonctions de règle et les appelles dans l'ordre. Elle ne s'occupe pas de la manière dont ces règles sont définies. À l'étape 2, elles étaient définies comme des fonctions nommées indépendantes. À l'étape 3, elles étaient définies comme des fonctions anonymes lambda. Maintenant, à l'étape 4, elles sont construites dynamiquement par la fonction buildMatchAndApplyFunctions à partir d'une liste de chaînes. De toute manière, la fonction plural agit de la même façon. |
Au cas où tout cela ne suffirait pas à vous tourner la tête, je dois ajouter qu'il y a une petite subtilité dans la définition de buildMatchAndApplyFunctions que je n'ai pas expliquée. Regardons à nouveau cette définition.
def buildMatchAndApplyFunctions((pattern, search, replace)):
>>> def foo((a, b, c)): ... print c ... print b ... print a >>> parameters = ('apple', 'bear', 'catnap') >>> foo(parameters) catnap bear apple
L'appel à la fonction foo se fait avec un tuple de trois éléments. Lorsque la fonction est appelée, les éléments sont assignés à trois variables locales à foo. |
Maintenant, examinons pourquoi il est nécessaire d'utiliser le développement automatique de tuple. patterns est une liste de tuples, chacun ayant trois éléments. Lorsque nous appelons map(buildMatchAndApplyFunctions, patterns), cela signifie que buildMatchAndApplyFunctions n'est pas appelé avec trois arguments. Utiliser map pour appliquer une liste à une fonction appelle cette fonction avec à chaque fois un seul paramètre : chacun des éléments de la liste. Dans le cas de patterns, chaque élément de la liste est un tuple, donc buildMatchAndApplyFunctions est à chaque fois appelé avec le tuple et nous utilisons le développement automatique de tuple dans la définition de buildMatchAndApplyFunctions pour assigner les éléments de ce tuple à des variables locales avec lesquelles nous pouvons travailler.
<< plural.py, étape 3 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
plural.py, étape 5 >> |