Chi*_*chi 34 python dictionary numpy scientific-computing scipy
我目前正在使用SciPy.integrate.ode在Python中实现复杂的微生物食品网.我需要能够轻松地将物种和反应添加到系统中,所以我必须编写一些非常通用的代码.我的方案看起来像这样:
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)
Run Code Online (Sandbox Code Playgroud)
所以,问题是,当我遍历字典中Species.sumOverAllReactionsForThisSpecies()和FermentationChamber.step(),是迭代顺序保证是相同的字典的,如果没有元素被添加或从第一个和最后一个迭代的字典中删除?也就是说,我可以假设在字典的每次迭代中创建的numpy数组的顺序不会变化吗?例如,如果字典具有格式{'Glucose':10,'Fructose':12},如果从该字典创建的数组将始终具有相同的顺序(无论该顺序是什么,只要这是确定性的).
对不起,我只是想让你知道我来自哪里.
tru*_*ppo 65
是的,如果未修改,则保证相同的订单.
请参阅此处的文档.
编辑:
关于如果更改值(但不添加/删除键)会影响订单,这就是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.
*/
Run Code Online (Sandbox Code Playgroud)
它似乎不是一个实现细节,而是语言的要求.
use*_*610 17
这取决于 Python 版本。
字典迭代顺序保证按插入顺序排列。
字典迭代顺序恰好是 CPython 实现中的插入顺序,但这不是该语言的书面保证。
键和值以任意顺序迭代,该顺序是非随机的,因 Python 实现而异,并取决于字典的插入和删除历史。如果在没有对字典进行干预的情况下迭代键、值和项目视图,项目的顺序将直接对应。https://docs.python.org/2/library/stdtypes.html#dictionary-view-objects
Python 2.6 添加了-R 选项作为(事实证明不够充分)防止散列泛洪攻击的保护。在 Python 2 中,启用受影响的字典迭代顺序(上面指定的属性仍然保留,但特定的迭代顺序会因程序的一次执行而异)。因此,默认情况下该选项处于关闭状态。
在 Python 3 中,-R 选项默认开启自 Python 3.3 起,这为 dict 迭代顺序添加了不确定性,因为每次运行 Python 解释器时,哈希计算的种子值都是随机生成的。这种情况一直持续到 CPython 3.6,它以某种方式更改了 dict 实现,以便条目的哈希值不会影响迭代顺序。
在 3.7 版更改: 字典顺序保证是插入顺序。此行为是 3.6 中 CPython 的实现细节。https://docs.python.org/3.8/library/stdtypes.html
Python 3.6 中的新功能:这个新实现的顺序保留方面被认为是一个实现细节,不应该被依赖(这可能会在未来发生变化,但希望在一些语言中使用这个新的 dict 实现)在更改语言规范以强制要求所有当前和未来 Python 实现的顺序保留语义之前发布版本;这也有助于保持与旧版本语言的向后兼容性,其中随机迭代顺序仍然有效,例如 Python 3.5)。https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-compactdict
如果没有对字典进行修改,答案是肯定的.请参阅此处的文档.
但是,字典在Python中本质上是无序的.通常,依靠字典来处理敏感的排序数据并不是最佳做法.
一个更强大的解决方案的例子是Django的SortedDict数据结构.
如果您希望订单保持一致,我会采取措施强制执行特定订单.虽然你可能能够说服自己订单得到保证,而你可能是对的,但对我来说这似乎很脆弱,对其他开发者来说这将是神秘的.
例如,你总是在你的问题中强调.在Python 2.5和2.6中它是相同的顺序是否重要?2.6和3.1?CPython和Jython?我不会指望那些.
我还建议不要依赖字典顺序是非随机的.
如果你想要一个内置的解决方案来排序你的字典,请阅读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)]
Run Code Online (Sandbox Code Playgroud)
Python 3.1 有一个collections.OrderedDict类可以用于此目的。它也非常高效:“所有方法的 Big-O 运行时间与常规字典相同。”
OrderedDict 本身的代码与Python 2.x 兼容,尽管一些继承的方法(来自_abcoll模块)确实使用了仅 Python 3 的功能。但是,可以轻松地将它们修改为 2.x 代码。