web-dev-qa-db-ja.com

Python辞書の順序は繰り返しで保証されていますか?

私は現在、Python using 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}の場合、この辞書から作成された配列がalways同じ順序を持っている(それが確定的である限り、その順序が何であるかは関係ありません)。

メガポストでごめんなさい、私がどこから来たのかをあなたに知らせたかっただけです。

35
Chinmay Kanchi

Python 3.1には、この目的で使用できる collections.OrderedDict クラスがあります。 「すべてのメソッドのBig-O実行時間は、通常の辞書の場合と同じです。」

OrderedDictのコード 自体はPython 2.xと互換性がありますが、継承された一部のメソッド( _ abcoll モジュールから)はPythonを使用します3-機能のみ。ただし、最小限の労力で2.xコードに変更できます。

4

はい、変更されない場合、同じ注文が保証されます。

Docs here を参照してください。

編集:

値を変更すると(ただし、キーの追加や削除ではなく)順序に影響するかどうかについては、Cソースのコメントに次のように記載されています。

/* 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.
 */

実装の詳細ではなく、言語の要件のようです。

67
truppo

辞書にnoの変更が加えられた場合、答えは「はい」です。 こちらのドキュメントを参照

ただし、Pythonでは本来、辞書は順序付けされていません。一般に、機密性の高いソート済みデータを辞書に依存することはベストプラクティスではありません。

より堅牢なソリューションの例は DjangoのSortedDictデータ構造 です。

8
Gabriel Hurley

順序に一貫性を持たせたい場合は、特定の順序を強制するために何かを行います。順序が保証されていることは納得できるかもしれませんが、正しいかもしれませんが、私には壊れやすいようで、他の開発者には不思議です。

たとえば、質問でalwaysを強調します。 Python 2.5と2.6?2.6と3.1?CPythonとJythonで同じ順序であることが重要ですか?私はそれらに頼りません。

7
Ned Batchelder

辞書の順序がランダムではないという事実に依存しないこともお勧めします。

辞書をソートするための組み込みのソリューションが必要な場合は、次をお読みください 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'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
Derek Litz

Pythonバージョンによって異なります。

Python 3.7以降

辞書の反復順序は、挿入順になっていることが保証されています。

Python 3.6

辞書の反復順序は、CPython実装での挿入順になっていますが、文書化された言語の保証ではありません。

以前のバージョン

正確なバージョンによって異なります。一部のCPython 3.xバージョンでは、順序が意図的にランダム化されていることがよくありました。

ソース

バージョン3.7で変更:辞書順は挿入順であることが保証されています。この動作は、3.6からのCPythonの実装の詳細でした。 https://docs.python.org/3.8/library/stdtypes.html

0
user7610