Python中集的迭代顺序

时间:2010-08-04 14:08:16

标签: python iteration set

如果我有两个相同的集合,意味着a == b给我True,它们会有相同的迭代顺序吗?我试过了,它的确有效:

>>> foo = set("abc")
>>> bar = set("abc")
>>> zip(foo, bar)
[('a', 'a'), ('c', 'c'), ('b', 'b')]

我的问题是,我是幸运的,还是保证了这种行为?

5 个答案:

答案 0 :(得分:21)

它们不是只是巧合,它们是相同的:实现恰好是确定性的,因此创建相同的集合两次产生相同的顺序。但Python并不保证。

如果您以两种不同的方式创建相同的集合:

n = set("abc")
print n

m = set("kabc")
m.remove("k")
print m

...你可以得到不同的顺序:

set(['a', 'c', 'b'])
set(['a', 'b', 'c'])

答案 1 :(得分:4)

你很幸运,订单无法保证。唯一能保证的是集合将具有相同的元素。

如果您需要某种可预测性,可以按照以下方式对其进行排序:zip(sorted(foo), sorted(bar))

答案 2 :(得分:4)

没有:

>>> 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。我不知道是否需要__hash__覆盖。我只是尝试了一些我认为会破坏它的东西,而且确实如此。

答案 3 :(得分:1)

是的,你很幸运。例如见:

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)

这给了我结果:

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)]

答案 4 :(得分:0)

我说你很幸运。但是,也可能是因为集合中的元素是相同的,所以它们以相同的顺序存储。这种行为不是你想要依赖的。

相关问题