Les ensembles et les dict sont optimisés pour différents cas d'utilisation. L'utilisation principale d'un ensemble est le test d'appartenance rapide, qui est indépendant de l'ordre.Pour les dictés, le coût de la recherche est l'opération la plus critique et la clé est plus susceptible d'être présente. Avec les ensembles, la présence ou l'absence d'un élément n'est pas connue à l'avance et l'implémentation de l'ensemble doit donc être optimisée pour le cas trouvé et non trouvé. En outre, certaines optimisations pour les opérations d'ensemble courantes telles que l'union et l'intersection rendent difficile la conservation de l'ordre des ensembles sans dégrader les performances.
Bien que les deux structures de données soient basées sur le hachage, il est faux de penser que les ensembles sont simplement implémentés comme des dict avec des valeurs nulles. Même avant l'implémentation compacte de dict dans CPython 3.6, les implémentations set et dict différaient déjà considérablement, avec peu de réutilisation de code. Par exemple, les dict utilisent le sondage aléatoire, mais les ensembles utilisent une combinaison de sondage linéaire et d'adressage ouvert, pour améliorer la localisation du cache. La sonde linéaire initiale ( 9 étapes par défaut dans CPython) vérifiera une série de paires clé / hachage adjacentes, améliorant les performances en réduisant le coût de la gestion des collisions de hachage - l'accès mémoire consécutif est moins cher que les sondes dispersées.
Il serait possible en théorie de changer l'implémentation d'ensemble de CPython pour qu'elle soit similaire à la dictée compacte, mais dans la pratique, il y a des inconvénients, et des développeurs principaux notables étaient opposés à faire un tel changement.
Les décors ne sont pas classés. (Pourquoi? Les modèles d'utilisation sont différents. De plus, la mise en œuvre est différente.)
- Guido van Rossum
Les ensembles utilisent un algorithme différent qui n'est pas aussi modifiable pour conserver l'ordre d'insertion. Les opérations d'ensemble à ensemble perdent leur flexibilité et leurs optimisations si la commande est requise. Les mathématiques des ensembles sont définies en termes d'ensembles non ordonnés. En bref, la mise en ordre n'est pas dans un avenir immédiat.
- Raymond Hettinger
Une discussion détaillée sur l'opportunité de compacter les ensembles pour 3.7, et des réponses sur les raisons pour lesquelles il a été décidé de ne pas le faire, peuvent être trouvées dans les listes de diffusion python-dev.
En résumé, les points principaux sont que les modèles d'utilisation sont différents (les ordres de commande d'insertion tels que ** kwargs sont utiles , moins pour les ensembles), les économies d'espace pour les ensembles de compactage sont moins importantes (car il n'y a que des clés et un tableau de hachage pour densifier, par opposition aux clés, hachages et valeurs), et l'optimisation de sondage linéaire susmentionnée dans les ensembles est incompatible avec une implémentation compacte.
Je reproduis ci-dessous le billet de Raymond qui couvre les points les plus importants.
Le 14 septembre 2016, à 15 h 50, Eric Snow a écrit:
Ensuite, je ferai de même pour les décors.
Sauf si j'ai mal compris, Raymond était opposé à un changement similaire à définir.
C'est vrai. Voici quelques réflexions sur le sujet avant que les gens ne commencent à courir sauvage.
Pour le dict compact, les économies d'espace ont été un gain net avec l'espace supplémentaire consommé par les indices et la surutilisation des tableaux clé / valeur / hachage étant plus que compensée par l'amélioration de la densité des tableaux clé / valeur / hachage. Cependant, pour les ensembles, le net était beaucoup moins favorable car nous avons encore besoin des indices et de la surutilisation mais ne pouvons compenser le coût d'espace qu'en densifiant seulement deux des trois tableaux. En d'autres termes, le compactage a plus de sens lorsque vous avez perdu de l'espace pour les clés, les valeurs et les hachages. Si vous perdez l'un de ces trois, il cesse d'être convaincant.
Le modèle d'utilisation des ensembles est différent des modèles. Le premier a plus de recherches à succès. Ce dernier a tendance à avoir moins de recherches de clés manquantes. De plus, certaines des optimisations pour les opérations set-to-set rendent difficile la conservation de l'ordre des sets sans affecter les performances.
J'ai poursuivi une voie alternative pour améliorer les performances de l'ensemble. Au lieu de compacter (ce qui n'était pas beaucoup de gain d'espace et entraînait le coût d'une indirection supplémentaire), j'ai ajouté une sonde linéaire pour réduire le coût des collisions et améliorer les performances du cache. Cette amélioration est incompatible avec l'approche de compactage que j'ai préconisée pour les dictionnaires.
Pour l'instant, l'effet secondaire de commande sur les dictionnaires n'est pas garanti, il est donc prématuré de commencer à insister pour que les ensembles deviennent également ordonnés. Les documents établissent déjà un lien vers une recette pour créer un ensemble ordonné (
https://code.activestate.com/recipes/576694/ ), mais il semble que l'adoption ait été presque nulle. De plus, maintenant qu'Eric Snow nous a donné un OrderedDict rapide, il est plus facile que jamais de construire un OrderedSet à partir de MutableSet et OrderedDict, mais encore une fois je n'ai observé aucun intérêt réel parce que l'analyse de données set-to-set typique n'a pas vraiment besoin ou souci de commander. De même, l'utilisation principale des tests d'appartenance rapides est indépendante de l'ordre.
Cela dit, je pense qu'il est possible d'ajouter des implémentations d'ensembles alternatifs à PyPI. En particulier, il existe des cas spéciaux intéressants pour les données commandables où les opérations set-to-set peuvent être accélérées en comparant des plages entières de clés (voir
https://code.activestate.com/recipes/230113-implementation-of- sets-using-sorted-lists
pour un point de départ). IIRC, PyPI a déjà du code pour les filtres de floraison et le hachage de coucous.
Je comprends qu'il est excitant d'avoir un bloc de code majeur accepté dans le noyau Python, mais cela ne devrait pas ouvrir la porte à des réécritures plus importantes d'autres types de données, sauf si nous sommes sûrs que cela est justifié.
- Raymond Hettinger
De [Python-Dev] Python 3.6 dict devient compact et obtient une version privée; et les mots clés sont commandés , septembre 2016.