Iteration order of sets in Python
If I have two identical sets, meaning a == b
gives me True
, will they have the same iteration order? I tried it, and it works:
>>> foo = set("abc")
&开发者_Go百科gt;>> bar = set("abc")
>>> zip(foo, bar)
[('a', 'a'), ('c', 'c'), ('b', 'b')]
My question is, was I lucky, or is this behavior guaranteed?
It wasn't just a coincidence that they came out the same: the implementation happens to be deterministic, so creating the same set twice produces the same ordering. But Python does not guarantee that.
If you create the same set in two different ways:
n = set("abc")
print n
m = set("kabc")
m.remove("k")
print m
...you can get different ordering:
set(['a', 'c', 'b'])
set(['a', 'b', 'c'])
You were lucky, the order is not guaranteed. The only thing that's guaranteed is that the sets will have the same elements.
If you need some sort of predictability, you could sort them like this: zip(sorted(foo), sorted(bar))
.
No.:
>>> class MyStr( str ):
... def __hash__( self ):
... return 0
...
>>> a = MyStr( "a" )
>>> b = MyStr( "b" )
>>> c = MyStr( "c" )
>>> foo = { a, b, c }
>>> foo
{'c', 'b', 'a'}
>>> bar = { b, a, c }
>>> foo is bar
False
>>> foo == bar
True
>>> list( zip( foo, bar ) )
[('c', 'c'), ('b', 'a'), ('a', 'b')]
P.S. I have no idea if the __hash__
override is necessary. I just tried something I thought would break this, and it did.
Yes, you were lucky. See for example:
import random
r = [random.randint(1,10000) for i in range(20)]
foo = set(r)
r.sort(key=lambda _: random.randint(1,10000))
bar = set(r)
print foo==bar
print zip(foo, bar)
Which gave me the result:
True
[(3234, 3234), (9393, 9393), (9361, 1097), (1097, 5994), (5994, 2044), (1614, 1614), (6074, 4377), (4377, 9361), (5202, 5202), (2355, 2355), (1012, 1012), (7349, 7349), (6198, 6198), (8489, 8489), (7929, 7929), (6556, 6074), (6971, 6971), (2044, 6556), (7133, 7133), (383, 383)]
I'd say you got lucky. Though, it might also be that, since the elements in the set were the same, they were stored in the same order. This behavior is not something you'd want to rely on.
精彩评论