L'ordre d'un dictionnaire Python est-il garanti sur les itérations?

J'implémente actuellement un réseau alimentaire microbien complexe en Python en utilisant SciPy.intégrer.ode . J'ai besoin de la capacité d'ajouter facilement des espèces et des réactions au système, donc je dois coder quelque chose de assez général. Mon schéma ressemble à ceci:

class Reaction(object):
    def __init__(self):
        #stuff common to all reactions
    def __getReactionRate(self, **kwargs):
        raise NotImplementedError

... Reaction subclasses that 
... implement specific types of reactions


class Species(object):
    def __init__(self, reactionsDict):
        self.reactionsDict = reactionsDict
        #reactionsDict looks like {'ReactionName':reactionObject, ...}
        #stuff common to all species

    def sumOverAllReactionsForThisSpecies(self, **kwargs):
        #loop over all the reactions and return the 
        #cumulative change in the concentrations of all solutes

...Species subclasses where for each species
... are defined and passed to the superclass constructor

class FermentationChamber(object):
    def __init__(self, speciesList, timeToSolve, *args):
        #do initialization

    def step(self):
        #loop over each species, which in turn loops 
        #over each reaction inside it and return a 
        #cumulative dictionary of total change for each 
        #solute in the whole system


if __name__==__main__:
    f = FermentationChamber(...)

    o  = ode(...) #initialize ode solver

    while o.successful() and o.t<timeToSolve:
         o.integrate()

    #process o.t and o.y (o.t contains the time points
    #and o.y contains the solution matrix)

Donc, la question est, quand j'itère sur les dictionnaires dans Species.sumOverAllReactionsForThisSpecies() et FermentationChamber.step(), l'ordre d'itération des dictionnaires est-il garanti le même si aucun élément n'est ajouté ou supprimé des dictionnaires entre la première et la dernière itération? Autrement dit, Puis-je supposer que l'ordre du tableau numpy créé à chaque itération du dictionnaire ne variera pas? Par exemple, si un dictionnaire a le format {'Glucose':10, 'Fructose':12}, si un tableau créé à partir de ce dictionnaire aura toujours le même ordre (peu importe cet ordre, tant qu'il est déterministe).

Désolé pour le méga-post, je voulais juste vous faire savoir d'où je viens.

25
demandé sur Chinmay Kanchi 2010-01-13 01:42:01

5 réponses

Python 3.1 a une collection .OrderedDict classe qui peut être utilisée à cette fin. C'est aussi très efficace: "les temps de fonctionnement de Big-O pour toutes les méthodes sont les mêmes que pour les dictionnaires réguliers."

Le code pour OrderedDict lui-même est compatible avec Python 2.x, bien que certaines méthodes héritées (du module _abcoll) utilisent des fonctionnalités Python 3 uniquement. Cependant, ils peuvent être modifiés à 2.code x avec un minimum d'effort.

3
répondu Johannes Sasongko 2010-01-13 06:08:20

Oui, la même commande est garantie si elle n'est pas modifiée.

Voir les documents ici .

Modifier:

En ce qui concerne Si changer la valeur (mais ne pas ajouter / supprimer une clé)affectera l'ordre, c'est ce que les commentaires dans la C-source disent:

/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
 * dictionary if it's merely replacing the value for an existing key.
 * This means that it's safe to loop over a dictionary with PyDict_Next()
 * and occasionally replace a value -- but you can't insert new keys or
 * remove them.
 */

, Il semble que ce n'est pas un détail d'implémentation, mais une exigence de la langue.

51
répondu truppo 2016-01-01 08:52:40

À condition que non des modifications soient apportées au Dictionnaire, la réponse est oui. Voir les documents ici.

Cependant, les dictionnaires ne sont pas ordonnés par nature en Python. En général, ce n'est pas la meilleure pratique de s'appuyer sur des dictionnaires pour les données triées sensibles.

Un exemple de solution plus robuste serait la structure de données SortedDict de Django .

8
répondu Gabriel Hurley 2014-11-13 09:40:38

Si vous voulez que l'ordre soit cohérent, je ferais quelque chose pour forcer un ordre particulier. Bien que vous pourriez être en mesure de vous convaincre que l'ordre est garanti, et vous pourriez avoir raison, il me semble fragile, et il sera mystérieux pour les autres développeurs.

Par exemple, vous insistez sur Toujours dans votre question. Est-il important que ce soit le même ordre dans Python 2.5 et 2.6? 2.6 et 3.1? CPython et Jython? Je ne voudrais pas compter sur ceux.

7
répondu Ned Batchelder 2010-01-12 22:49:12

Je recommande également de ne pas compter sur le fait que l'ordre des dictionnaires est non aléatoire.

Si vous voulez une solution intégrée pour trier votre dictionnaire, lisez http://www.python.org/dev/peps/pep-0265/

Voici le matériel le plus pertinent:

Cette PPE est rejetée parce que la nécessité pour elle a été largement rempli par la fonction intégrée triée () de Py2.4:

    >>> sorted(d.iteritems(), key=itemgetter(1), reverse=True)
    [('b', 23), ('d', 17), ('c', 5), ('a', 2), ('e', 1)]

or for just the keys:

    >>> sorted(d, key=d.__getitem__, reverse=True)
    ['b', 'd', 'c', 'a', 'e']

Also, Python 2.5's heapq.nlargest() function addresses the common use
case of finding only a few of the highest valued items:

    >>> nlargest(2, d.iteritems(), itemgetter(1))
    [('b', 23), ('d', 17)]
6
répondu Derek Litz 2010-01-12 22:54:33