Является ли порядок словаря Python гарантированным за итерации?

В настоящее время я внедряю сложную микробную еду в Python, используя SciPy.integrate.ode. Мне нужна способность легко добавлять виды и реакции в систему, поэтому я должен кодировать что-то довольно общее. Моя схема выглядит примерно так:

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)

Итак, вопрос в том, что когда я повторяю словари в Species.sumOverAllReactionsForThisSpecies() и FermentationChamber.step(), это итерационный порядок словарей, гарантированных одинаковым, если ни один элемент не добавляется или не удаляется из словарей между первым и последняя итерация? То есть, могу ли я предположить, что порядок массива numpy, созданный на каждой итерации из словаря, не изменится? Например, если словарь имеет формат {'Glucose': 10, 'Fructose': 12}, если Array, созданный из этого словаря, всегда будет иметь тот же порядок (неважно, что это за заказ, пока он детерминирован).

Извините за мега-пост, я просто хотел сообщить, откуда я.

Ответ 1

Python 3.1 имеет класс collections.OrderedDict, который может быть использован для этой цели. Он также очень эффективен: "Время выполнения Big-O для всех методов такое же, как для обычных словарей".

code для OrderedDict сам по себе совместим с Python 2.x, хотя некоторые унаследованные методы (из _abcoll) используют функции только для Python 3. Тем не менее, они могут быть изменены с кодом 2.x с минимальными усилиями.

Ответ 2

Да, тот же порядок гарантирован, если он не изменен.

См. docs здесь.

Edit:

Что касается изменения значения (но не добавления/удаления ключа), это повлияет на порядок, это то, что комментарии в C-источнике говорят:

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

Похоже, что это не деталь реализации, а требование языка.

Ответ 3

Если в словарь не внесены изменения, ответ будет да. Смотрите здесь.

Однако в Python словари неупорядочены по своей природе. В целом, это не лучшая практика полагаться на словари для чувствительных отсортированных данных.

Примером более надежного решения будет структура данных Django SortedDict.

Ответ 4

Если вы хотите, чтобы заказ был последовательным, я сделал бы что-то, чтобы заставить определенный порядок. Хотя вы, возможно, сможете убедить себя, что заказ гарантирован, и вы можете быть правы, это кажется хрупким для меня, и это будет загадочно для других разработчиков.

Например, вы всегда подчеркиваете свой вопрос. Важно ли, чтобы это был тот же порядок в Python 2.5 и 2.6? 2,6 и 3,1? CPython и Jython? Я бы не стал рассчитывать на них.

Ответ 5

Я также рекомендовал бы не полагаться на то, что порядок словарей неслучайен.

Если вы хотите, чтобы встроенное решение для сортировки вашего словаря прочитало http://www.python.org/dev/peps/pep-0265/

Вот наиболее подходящий материал:

Этот PEP отклоняется, поскольку потребность в нем была в значительной степени   выполненный с помощью встроенной функции Py2.4 sorted():

    >>> 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 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)]