Can python create a dictionary from a list comprehension?

Duncan Booth duncan.booth at invalid.invalid
Mon May 28 06:14:31 EDT 2007


"Wim Vogelaar" <wim.vogelaar at mc2world dot org> wrote:

> 
>>
>> why this output isn't ordered, giving:
>> {2: 3, 4: 5, 6: 7, 8: 9, 10: 11 }
>>
>>
> 
> I made the original list two elements longer: a = 
> [1,2,3,4,5,6,7,8,9,10,11,12]
> 
> and to my surprise the output is now ordered, giving: {2: 3, 4: 5, 6:
> 7, 8: 9, 10: 11, 12: 13}
> 
... and it will become unordered again when you get up to storing 32 in the 
dictionary, and ordered again when you get up to 44.

It is an unfortunate side-effect of the way that Python dictionaries work 
that it often appears when you store small integers as though they are 
being stored sorted. In fact the order depends on the order in which you 
inserted the values into the dictionary, the current size allocated to the 
dictionary, and whether any slots have previously been occupied by other 
values.

In your original output:

  {8: 9, 2: 3, 4: 5, 10: 11, 6: 7}

the keys 2, 4, and 6 are inserted into the 2nd, 4th, 6th slots of the 
dictionary (counting from 0 and there are initially 8 slots), 8 goes into 
the 0th slot, 10 would go into the 2nd slot except that is filled so it 
ends up in the 5th slot.

When you insert 12, the initial dictionary is too full (it never fills all 
the slots), so it is resized to have 32 slots. Again the 32 wraps round to 
the 0th slot and higher values all collide with filled slots so they end up 
in less obvious positions:

>>> for i in range(12,42,2):
	print dict.fromkeys(range(2,i,2))

	
{8: None, 2: None, 4: None, 10: None, 6: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None, 22: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None, 22: None, 24: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None, 22: None, 24: None, 26: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None}
{2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: None, 16: 
None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None, 30: None}
{32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 14: 
None, 16: None, 18: None, 20: None, 22: None, 24: None, 26: None, 28: None, 
30: None}
{32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 34: 
None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None, 26: None, 
28: None, 30: None}
{32: None, 2: None, 4: None, 6: None, 8: None, 10: None, 12: None, 34: 
None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None, 36: None, 
26: None, 28: None, 30: None}
{32: None, 2: None, 4: None, 38: None, 6: None, 8: None, 10: None, 12: 
None, 34: None, 14: None, 16: None, 18: None, 20: None, 22: None, 24: None, 
36: None, 26: None, 28: None, 30: None}

The fact that integers hash to themselves may be unlikely to change, but 
the sizes of the hash tables, or the conflict resolution strategy when an 
insertion hits an already used slot could all vary in other versions of 
Python.



More information about the Python-list mailing list