This is more a response to Python 3.41 A set before it was closed as a duplicate.
The others are right: don’t rely on the order. Don’t even pretend there is one.
That said, there is one thing you can rely on:
list(myset) == list(myset)
That is, the order is stable.
Understanding why there is a perceived order requires understanding a few things:
From the top:
A hash set is a method of storing random data with really fast lookup times.
It has a backing array:
# A C array; items may be NULL,
# a pointer to an object, or a
# special dummy object
_ _ 4 _ _ 2 _ _ 6
We shall ignore the special dummy object, which exists only to make removes easier to deal with, because we won’t be removing from these sets.
In order to have really fast lookup, you do some magic to calculate a hash from an object. The only rule is that two objects which are equal have the same hash. (But if two objects have the same hash they can be unequal.)
You then make in index by taking the modulus by the array length:
hash(4) % len(storage) = index 2
This makes it really fast to access elements.
Hashes are only most of the story, as hash(n) % len(storage)
and hash(m) % len(storage)
can result in the same number. In that case, several different strategies can try and resolve the conflict. CPython uses “linear probing” 9 times before doing complicated things, so it will look to the left of the slot for up to 9 places before looking elsewhere.
CPython’s hash sets are stored like this:

A hash set can be no more than 2/3 full. If there are 20 elements and the backing array is 30 elements long, the backing store will resize to be larger. This is because you get collisions more often with small backing stores, and collisions slow everything down.

The backing store resizes in powers of 4, starting at 8, except for large sets (50k elements) which resize in powers of two: (8, 32, 128, …).
So when you create an array the backing store is length 8. When it is 5 full and you add an element, it will briefly contain 6 elements. 6 > ²??·8
so this triggers a resize, and the backing store quadruples to size 32.
Finally, hash(n)
just returns n
for numbers (except 1
which is special).
So, let’s look at the first one:
v_set = {88,11,1,33,21,3,7,55,37,8}
len(v_set)
is 10, so the backing store is at least 15(+1) after all items have been added. The relevant power of 2 is 32. So the backing store is:
__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
We have
hash(88) % 32 = 24
hash(11) % 32 = 11
hash(1) % 32 = 1
hash(33) % 32 = 1
hash(21) % 32 = 21
hash(3) % 32 = 3
hash(7) % 32 = 7
hash(55) % 32 = 23
hash(37) % 32 = 5
hash(8) % 32 = 8
so these insert as:
__ 1 __ 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
33 ? Can't also be where 1 is;
either 1 or 33 has to move
So we would expect an order like
{[1 or 33], 3, 37, 7, 8, 11, 21, 55, 88}
with the 1 or 33 that isn’t at the start somewhere else. This will use linear probing, so we will either have:
?
__ 1 33 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
or
?
__ 33 1 3 __ 37 __ 7 8 __ __ 11 __ __ __ __ __ __ __ __ __ 21 __ 55 88 __ __ __ __ __ __ __
You might expect the 33 to be the one that’s displaced because the 1 was already there, but due to the resizing that happens as the set is being built, this isn’t actually the case. Every time the set gets rebuilt, the items already added are effectively reordered.
Now you can see why
{7,5,11,1,4,13,55,12,2,3,6,20,9,10}
might be in order. There are 14 elements, so the backing store is at least 21+1, which means 32:
__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __
1 to 13 hash in the first 13 slots. 20 goes in slot 20.
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ __ __ 20 __ __ __ __ __ __ __ __ __ __ __
55 goes in slot hash(55) % 32
which is 23:
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ __ __ 20 __ __ 55 __ __ __ __ __ __ __ __
If we chose 50 instead, we’d expect
__ 1 2 3 4 5 6 7 8 9 10 11 12 13 __ __ __ __ 50 __ 20 __ __ __ __ __ __ __ __ __ __ __
And lo and behold:
{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 20, 50}
#>>> {1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 50, 20}
pop
is implemented quite simply by the looks of things: it traverses the list and pops the first one.
This is all implementation detail.