采用可清洗对象(如dict
键或set
项目)的容器.因此,字典只能有一个带有值的键1
,1.0
或者True
等等.(注意:有些简化 - 允许哈希冲突,但这些值被认为是相等的)
我的问题是:解析顺序是否定义良好,是否可以跨实现预测结果对象?例如,OSX Python 2.7.11和3.5.1解释dict
如下:
>>> { True: 'a', 1: 'b', 1.0: 'c', (1+0j): 'd' } {True: 'd'}
在这种情况下,似乎保留了第一个键和最后一个值.
类似,在以下情况下set
:
>>> { True, 1, 1.0, (1+0j) } set([(1+0j)])
这里似乎保留了最后一项.
但(如评论中所述):
>>> set([True, 1, 1.0]) set([True])
现在保留了iterable中的第一个.
文档指出项目的顺序(例如in dict.items
)是未定义的,但我的问题是指构造 dict
或set
对象的结果.
现在已经在最近的python版本中修复了这个bug,正如@jsf的回答中所解释的那样
字典显示器
如果给出了逗号分隔的键/数据对序列,则从左到右计算它们以定义字典的条目:每个键对象用作字典中的键以存储相应的数据.这意味着您可以在键/基准列表中多次指定相同的键,并且该键的最终字典值将是给定的最后一个键.
与list和set comprehensions相反,dict理解需要两个用冒号分隔的表达式,后跟通常的"for"和"if"子句.运行理解时,生成的键和值元素将按照生成的顺序插入到新字典中.
设置显示
集合显示产生新的可变集合对象,内容由表达式序列或理解指定.当提供以逗号分隔的表达式列表时,将从左到右计算其元素并将其添加到set对象.当提供理解时,该集合由理解产生的元素构成.
调用set构造函数或使用理解和普通文字有所不同.
def f1(): return {x for x in [True, 1]} def f2(): return set([True, 1]) def f3(): return {True, 1} print(f1()) print(f2()) print(f3()) import dis print("f1") dis.dis(f1) print("f2") dis.dis(f2) print("f3") dis.dis(f3)
输出:
{True} {True} {1}
如何创建它们会影响结果:
605 0 LOAD_CONST 1 ( at 0x7fd17dc9a270, file "/home/padraic/Dropbox/python/test.py", line 605>)
3 LOAD_CONST 2 ('f1..')
6 MAKE_FUNCTION 0
9 LOAD_CONST 3 (True)
12 LOAD_CONST 4 (1)
15 BUILD_LIST 2
18 GET_ITER
19 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
22 RETURN_VALUE
f2
608 0 LOAD_GLOBAL 0 (set)
3 LOAD_CONST 1 (True)
6 LOAD_CONST 2 (1)
9 BUILD_LIST 2
12 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
15 RETURN_VALUE
f3
611 0 LOAD_CONST 1 (True)
3 LOAD_CONST 2 (1)
6 BUILD_SET 2
9 RETURN_VALUE
BUILD_SET
当您传递由逗号分隔的纯文字时,Python仅运行字节码:
当提供以逗号分隔的表达式列表时,将从左到右计算其元素并将其添加到set对象.
理解线:
当提供理解时,该集合由理解产生的元素构成.
因此,感谢Hamish提交错误报告BUILD_SET
,根据Raymond Hettinger在链接中的评论确实归结为操作码.罪魁祸首是Python/ceval.c中的BUILD_SET操作码,它不必要地向后循环,其实现如下:
TARGET(BUILD_SET) { PyObject *set = PySet_New(NULL); int err = 0; if (set == NULL) goto error; while (--oparg >= 0) { PyObject *item = POP(); if (err == 0) err = PySet_Add(set, item); Py_DECREF(item); } if (err != 0) { Py_DECREF(set); goto error; } PUSH(set); DISPATCH(); }