Je suis un débutant en python et je viens d’apprendre une technique impliquant des dictionnaires et des fonctions. La syntaxe est simple et cela semble être une chose triviale, mais mes sens python sont picotements. Quelque chose me dit que c'est un concept profond et très pythonique et je ne comprends pas tout à fait son importance. Quelqu'un peut-il nommer cette technique et expliquer comment / pourquoi elle est utile?
La technique consiste à utiliser un dictionnaire python et une fonction à utiliser. Vous insérez un élément supplémentaire dans le dict, dont la valeur est le nom de la fonction. Lorsque vous êtes prêt à appeler la fonction, vous émettez l'appel indirectement en vous référant à l'élément dict, pas à la fonction par son nom.
L'exemple sur lequel je travaille est tiré de Learn Python The Hard Way, 2e éd. (C'est la version disponible lorsque vous vous inscrivez via Udemy.com ; malheureusement, la version HTML gratuite en direct est actuellement Ed 3 et n'inclut plus cet exemple).
Paraphraser:
# make a dictionary of US states and major cities
cities = {'San Diego':'CA', 'New York':'NY', 'Detroit':'MI'}
# define a function to use on such a dictionary
def find_city (map, city):
# does something, returns some value
if city in map:
return map[city]
else:
return "Not found"
# then add a final dict element that refers to the function
cities['_found'] = find_city
Alors les expressions suivantes sont équivalentes. Vous pouvez appeler la fonction directement ou en référençant l'élément dict dont la valeur est la fonction.
>>> find_city (cities, 'New York')
NY
>>> cities['_found'](cities, 'New York')
NY
Quelqu'un peut-il expliquer de quelle langue il s'agit, et peut-être de la "vraie" programmation? Cet exercice de jouet était suffisant pour m'apprendre la syntaxe, mais ne m'a pas pris tout le chemin.
la source
Réponses:
Utiliser un dict vous permet de traduire la clé en appelable. La clé n'a pas besoin d'être codée en dur, comme dans votre exemple.
Généralement, il s'agit d'une forme de répartition de l'appelant, dans laquelle vous utilisez la valeur d'une variable pour vous connecter à une fonction. Supposons qu'un processus réseau vous envoie des codes de commande, un mappage de répartition vous permet de convertir facilement les codes de commande en code exécutable:
Notez que la fonction que nous appelons maintenant dépend entièrement de la valeur de
command
. La clé ne doit pas nécessairement correspondre non plus; il n'est même pas nécessaire que ce soit une chaîne, vous pouvez utiliser tout ce qui peut être utilisé comme clé et convient à votre application spécifique.L'utilisation d'une méthode de répartition est plus sûre que d'autres techniques, telles que
eval()
, car elle limite les commandes autorisées à ce que vous avez défini auparavant. Par exemple, aucun attaquant ne va se faufilerls)"; DROP TABLE Students; --
devant une table de répartition.la source
dict
agit en tant que répartiteur (gestionnaire de commandes, invocateur, etc.).@ Martijn Pieters a bien expliqué la technique, mais je voulais clarifier quelque chose de votre question.
La chose importante à savoir est que vous ne stockez PAS "le nom de la fonction" dans le dictionnaire. Vous stockez une référence à la fonction elle-même. Vous pouvez voir cela en utilisant un
print
sur la fonction.f
est juste une variable qui référence la fonction que vous avez définie. L'utilisation d'un dictionnaire vous permet de regrouper des éléments similaires, mais ce n'est pas différent d'affecter une fonction à une variable différente.De même, vous pouvez passer une fonction en argument.
la source
Notez que la classe Python n'est en réalité qu'un sucre de syntaxe pour dictionnaire. Quand tu fais:
quand vous appelez
est vraiment la même chose que:
qui, après résolution du nom, est identique à:
Une technique utile consiste à mapper une entrée utilisateur sur des rappels. Par exemple:
Cela peut alternativement être écrit en classe:
la meilleure syntaxe de rappel dépend de l'application et du goût du programmeur. Le premier est un style plus fonctionnel, le dernier est plus orienté objet. Le premier peut sembler plus naturel si vous devez modifier les entrées du dictionnaire de fonctions de manière dynamique (éventuellement en fonction des entrées de l'utilisateur); ce dernier peut sembler plus naturel si vous avez un ensemble de mappages de préréglages différents qui peuvent être choisis de manière dynamique.
la source
5 * x
à5x
(pardonnez l'analogie simple).Il se peut que vous parliez de deux techniques qui me sautent à l’esprit, aucune des deux n'étant pythonique en ce sens qu’elles sont plus larges qu’un seul langage.
1. La technique de la dissimulation / encapsulation de l’information et de la cohésion (elles vont généralement de pair, alors je les associe).
Vous avez un objet qui a des données et vous attachez une méthode (comportement) qui est très cohérente avec les données. Si vous devez modifier la fonction, étendre la fonctionnalité ou apporter toute autre modification que les appelants n'auront pas à modifier (en supposant qu'aucune donnée supplémentaire ne doit être transmise).
2. Tableaux d'expédition
Pas le cas classique, car il n'y a qu'une seule entrée avec une fonction. Cependant, les tables de répartition sont utilisées pour organiser différents comportements à l'aide d'une clé, de sorte qu'elles peuvent être recherchées et appelées de manière dynamique. Je ne suis pas sûr que vous pensiez à cela, puisque vous ne faites pas référence à la fonction de manière dynamique, mais vous obtenez néanmoins une liaison tardive effective (appel "indirect").
Compromis
Une chose à noter est ce que vous ferez fonctionnera bien avec un espace de noms connu de clés. Cependant, vous courez le risque de collision entre les données et les fonctions avec un espace de noms de clés inconnu.
la source
Je publie cette solution qui, à mon avis, est assez générique et peut être utile car elle reste simple et facile à adapter à des cas spécifiques:
on peut aussi définir une liste où chaque élément est un objet fonction et utiliser la
__call__
méthode intégrée. Crédits à tous pour l'inspiration et la coopération."Le grand artiste est le simplificateur", Henri Frederic Amiel
la source