python - Dict/Set Parsing Order Consistency -
containers take hashable objects (such dict keys or set items). such, dictionary can have 1 key value 1, 1.0 or true etc. (note: simplified - hash collisions permitted, these values considered equal)
my question is: parsing order well-defined , resulting object predictable across implementations? example, osx python 2.7.11 , 3.5.1 interprets dict so:
>>> { true: 'a', 1: 'b', 1.0: 'c', (1+0j): 'd' } {true: 'd'} in case, appears first key , last value preserved.
similar, in case of set:
>>> { true, 1, 1.0, (1+0j) } set([(1+0j)]) here appears last item preserved.
but (as mentioned in comments):
>>> set([true, 1, 1.0]) set([true]) now first in iterable preserved.
the documentation notes order of items (for example in dict.items) undefined, question refers result of constructing dict or set objects.
- the bug fixed in recent versions of python explained in @jsf's answer
if comma-separated sequence of key/datum pairs given, evaluated left right define entries of dictionary: each key object used key dictionary store corresponding datum. means can specify same key multiple times in key/datum list, , final dictionary’s value key last 1 given.
a dict comprehension, in contrast list , set comprehensions, needs 2 expressions separated colon followed usual “for” , “if” clauses. when comprehension run, resulting key , value elements inserted in new dictionary in order produced.
a set display yields new mutable set object, contents being specified either sequence of expressions or comprehension. when comma-separated list of expressions supplied, elements evaluated left right , added set object. when comprehension supplied, set constructed elements resulting comprehension.
there difference in calling set constructor or using comprehension , plain literal.
def f1(): return {x 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) output:
{true} {true} {1} how created influences outcome:
605 0 load_const 1 (<code object <setcomp> @ 0x7fd17dc9a270, file "/home/padraic/dropbox/python/test.py", line 605>) 3 load_const 2 ('f1.<locals>.<setcomp>') 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 python runs build_set bytecode when pass pure literal separated commas per:
when comma-separated list of expressions supplied, elements evaluated left right , added set object.
the line comprehension:
when comprehension supplied, set constructed elements resulting comprehension.
so hamish filing bug report indeed come down build_set opcode per raymond hettinger's comment in link the culprit build_set opcode in python/ceval.c unnecessarily loops backwards, implementation of below:
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(); }
Comments
Post a Comment