1

How come that I can easily do a for-loop in Python to loop through all the elements of a dictionary in the order I appended the elements but there's no obvious way to access a specific element? When I say element I'm talking about a key+value pair.

I've looked through what some basic tutorials on Python says on dictionaries but not a single one answers my question, I can't find my answer in docs.python.org either.

According to: accessing specific elements from python dictionary (Senderies comment) a dict is supposed to be unordered but then why does the for-loop print them in the order I put them in?

Community
  • 1
  • 1
Johan
  • 605
  • 5
  • 16
  • So what's your question now? About the loop behaviour or accessing an element? I could be that the hashes generated for the keys appear in the same order as you inserted the keys... – Felix Kling Jul 15 '11 at 00:20
  • 1
    If you're iterating over your elements in the same order you put them in, I'd say you're lucky. I believe you're guaranteed to iterate over them in the same order _every time to iterate over them_ however that's not guaranteed to be the same order you inserted them. – ajwood Jul 15 '11 at 00:25
  • @Felix : Well, I guess I'm just confused in general about Pythons behavior in this matter, my question is more about why and not how. @ajwood : Hm, okay. – Johan Jul 15 '11 at 00:28

5 Answers5

7

You access a specific element in a dictionary by key. That's what a dictionary is. If that behavior isn't what you want, use something other than a dictionary.

a dict is supposed to be unordered but then why does the for-loop print them in the order I put them in?

Coincidence: basically, you happened to put them in in the order that Python prefers. This isn't too hard to do, especially with integers (ints are their own hashes and will tend to come out from a dict in ascending numeric order, though this is an implementation detail of CPython and may not be true in other Python implementations), and especially if you put them in in numerical order to begin with.

"Unordered" really means that you don't control the order, and it may change due to various implementation-specific criteria, so you should not rely on it. Of course when you iterate over a dictionary elements come out in some order.

If you need to be able to access dictionary elements by numeric index, there are lots of ways to do that. collections.OrderedDict is the standard way; the keys are always returned in the order you added them, so you can always do foo[foo.keys()[i]] to access the ith element. There are other schemes you could use as well.

kindall
  • 178,883
  • 35
  • 278
  • 309
5

Python dicts are accessed by hashing the key. So if you have any sort of a sizable dict and things are coming out in the order you put them in, then it's time to start betting on the lottery!

my_dict = {}
my_dict['a'] = 1
my_dict['b'] = 2
my_dict['c'] = 3
my_dict['d'] = 4

for k,v in my_dict.items():
    print k, v

yields:

a 1
c 3
b 2
d 4
Peter Rowell
  • 17,605
  • 2
  • 49
  • 65
0
d = {}
d['first'] = 1
d['second'] = 2
d['third'] = 3
print d
# prints {'seconds': 2, 'third': 3, 'first': 1}
# Hmm, just like the docs say, order of insertion isn't preserved.

print d['third']
# prints 3
# And there you have it: access to a specific element
Michael Kent
  • 1,736
  • 12
  • 11
  • I should probably have put more thought into how I wrote my question, the two previous answers were more what I was looking for but thanks anyway. – Johan Jul 15 '11 at 00:33
0

If you want to iterate through the items in insertion order, you should be using OrderedDict. A regular dict is not guaranteed to do the same, so you're asking for trouble later if you rely on it to do so.

If you want to access a particular item, you should access it by its key using the [] operator or the get() method. That's the primary function of a dict, after all.

ʇsәɹoɈ
  • 22,757
  • 7
  • 55
  • 61
0

Result of the hashing of several values varies according the values:

sometimes the order seems to be kept: following example with d_one

generaly, the order is not kept: following example with d_two

Believing that the order is anyway kept is only because you are deceived by particuliar cases in which the order is apparently conserved

d_one = {}

for i,x in enumerate((122,'xo','roto',885)):
    print x
    d_one[x] = i

print
for k in d_one:
    print k

print '\n=======================\n'

d_two = {}

for i,x in enumerate((122,'xo','roto','taratata',885)):
    print x
    d_two[x] = i

print
for k in d_two:
    print k

result

122
xo
roto
885

122
xo
roto
885

=======================

122
xo
roto
taratata
885

122
taratata
xo
roto
885

By the way, what you call "elements of a dictionary' are commonly called 'items of the dictionary' ( hence the methods items() and iteritems() of a dictionary)

eyquem
  • 26,771
  • 7
  • 38
  • 46