简体   繁体   English

Python dict 文字会按照它的编写顺序进行评估吗?

[英]Will a Python dict literal be evaluated in the order it is written?

Let's say that I've got a situation like this in Python:假设我在 Python 中遇到过这样的情况:

_avg = {'total':0.0, 'count':0}    # HACK: side-effects stored here

def procedure(n):
  _avg['count'] += 1
  _avg['total'] += n
  return n

def get_average():
  return _avg['total'] / _avg['count']

my_dict = {
  'key0': procedure(0),
  'key2': procedure(2),
  'key1': get_average()
}
assert(my_dict['key1'] == 1.0)

I know that the order of my_dict.keys() is undefined, but what I'm wondering is whether the initialization via a literal like this is guaranteed to happen in a particular order.我知道my_dict.keys()的顺序是未定义的,但我想知道的是,通过这样的文字进行的初始化是否保证以特定的顺序发生。 Will the value of my_dict['key1'] always be 1.0 as asserted? my_dict['key1']的值my_dict['key1']总是如断言的1.0

Dictionary evaluation order should be the same as written, but there is a outstanding bug where values are evaluated before the keys .字典求值顺序应该和写的一样,但是有一个突出的错误之前求 (The bug was finally fixed in Python 3.5). (该错误最终在 Python 3.5 中修复)。

Quoting from the reference documentation :引用参考文档

Python evaluates expressions from left to right. Python 从左到右计算表达式。

and from the bug report:并从错误报告:

Running the following code shows "2 1 4 3" , but in reference manual http://docs.python.org/reference/expressions.html#expression-lists the evaluation order described as {expr1: expr2, expr3: expr4}运行以下代码显示"2 1 4 3" ,但在参考手册http://docs.python.org/reference/expressions.html#expression-lists 中,评估顺序描述为{expr1: expr2, expr3: expr4}

 def f(i): print i return i {f(1):f(2), f(3):f(4)}

and Guido stated:圭多说:

I am sticking with my opinion from before: the code should be fixed.我坚持我以前的观点:代码应该被修复。 It doesn't look like assignment to me.对我来说这看起来不像是任务。

This bug is fixed in Python 3.5, so on Python 3.4 and earlier the values are still evaluated before the keys:此错误在 Python 3.5 中已修复,因此在 Python 3.4 及更早版本中,仍会在键之前评估值:

>>> import sys
>>> sys.version_info
sys.version_info(major=3, minor=4, micro=2, releaselevel='final', serial=0)
>>> def f(i):
...     print(i)
...     return i
... 
>>> {f(1):f(2), f(3):f(4)}
2
1
4
3
{1: 2, 3: 4}

Since your code doesn't require the keys to be evaluated first, your code is guaranteed to work correctly;由于您的代码不需要首先评估密钥,因此您的代码可以保证正常工作; key-value pairs are still evaluated in order even if the keys are evaluated after each corresponding value.即使在每个对应的值之后对键进行求值,键值对仍按顺序求值。

According to the Python docs regarding evaluation order , this should have well-defined behavior:根据有关评估顺序Python 文档,这应该具有明确定义的行为:

In the following lines, expressions will be evaluated in the arithmetic order of their suffixes:在以下几行中,表达式将按照其后缀的算术顺序进行计算:

 … {expr1: expr2, expr3: expr4} …

So, regardless of what order the items in a dict end up being iterated , the values (and keys!) of a literal dictionary expression will always be evaluated in the same order as they appear in my Python source code.因此,无论dict的项目最终被迭代的顺序如何,文字字典表达式的值(和键!)将始终按照它们在我的 Python 源代码中出现的顺序进行评估

The current behaviour on Python 3.4.2 can be very clearly seen in the disassembled bytecode: the values are evaluated before keys, not left-to-right.在反汇编的字节码中可以非常清楚地看到 Python 3.4.2 上的当前行为:在键之前评估值,而不是从左到右。

>>> dis.dis(lambda: {f('1'): f('2'), f('3'): f('4')})
  1           0 BUILD_MAP                2
              3 LOAD_GLOBAL              0 (f)
              6 LOAD_CONST               1 ('2')
              9 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             12 LOAD_GLOBAL              0 (f)
             15 LOAD_CONST               2 ('1')
             18 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             21 STORE_MAP
             22 LOAD_GLOBAL              0 (f)
             25 LOAD_CONST               3 ('4')
             28 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             31 LOAD_GLOBAL              0 (f)
             34 LOAD_CONST               4 ('3')
             37 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
             40 STORE_MAP
             41 RETURN_VALUE

However this also shows the reason why this is also not so straightforward to fix: the values and keys are expected by STORE_MAP in this order;然而,这也说明了为什么这也不是那么容易解决的原因: STORE_MAP按此顺序需要值和键; changing the order would either require adding aROT_TWO opcode after each pair, or STORE_MAP_EX opcode which would expect the pairs to be reversed;改变次序要么需要加入ROT_TWO每一对中,或之后操作码STORE_MAP_EX操作码,其将所期望的对被逆转; the first one would be a performance drop, whereas the second would mean yet another opcode to handle in every piece of code that deals with bytecode.第一个将是性能下降,而第二个将意味着在处理字节码的每一段代码中处理另一个操作码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM