1

Why is the order of the elements being changed only when it goes through the function call? what is deciding this order?

# test_set_order.py
def unpack(input):
    print('input is {}'.format(input))
    result = []
    for i in input:
        result.extend(i)
    return result

print(unpack({'A', 'B'}))

Executing the script above results in different outputs:

$ python test_set_order.py
input is {'B', 'A'}
['B', 'A']
$ python test_set_order.py
input is {'B', 'A'}
['B', 'A']
$ python test_set_order.py
input is {'A', 'B'}
['A', 'B']
$ python test_set_order.py
input is {'B', 'A'}
['B', 'A']
$ python test_set_order.py
input is {'A', 'B'}
['A', 'B']
$ python test_set_order.py
input is {'A', 'B'}
['A', 'B']

This is on python 3.6.5. On python 2.7.13 you always get the same order

It seems that order only gets changed after the function call. It doesn't happen before:

>>> bla = {'A','B'}; print(bla)
{'A', 'B'}
>>> bla = {'A','B'}; print(bla)
{'A', 'B'}
>>> bla = {'A','B'}; print(bla)
{'A', 'B'}
>>> bla = {'A','B'}; print(bla)
{'A', 'B'}
>>> bla = {'A','B'}; print([i for i in bla])
['A', 'B']
>>> bla = {'A','B'}; print([i for i in bla])
['A', 'B']
>>> bla = {'A','B'}; print([i for i in bla])
['A', 'B']
>>> bla = {'A','B'}; print([i for i in bla])
['A', 'B']
>>> bla = {'A','B'}; print([i for i in bla])
['A', 'B']

UPDATE:

seems that it has to do with the hashing and it is decided when the interpreter starts. This is enough to reproduce:

$ python -c "print({'A', 'B'})"
{'B', 'A'}
$ python -c "print({'A', 'B'})"
{'A', 'B'}

the value of 'A'.__hash__()) changes each time on python 3

fersarr
  • 3,399
  • 3
  • 28
  • 35
  • The hashing determines the order but these are undocumented and not guaranteed implementation details, don't use a set if you want a particular order – Chris_Rands Nov 07 '18 at 10:53
  • @Chris_Rands this is not the same question as the one you linked. Why does the order change only during the function call? and not in the other examples – fersarr Nov 07 '18 at 10:57
  • See my 2nd dupe https://stackoverflow.com/questions/49896202/indeterministic-sets-in-python-2-and-3, the reason is that hash randomization is enabled by default in Python 3, you can switch it off via `PYTHONHASHSEED` – Chris_Rands Nov 07 '18 at 11:03
  • Cool, thanks! that one is better :) – fersarr Nov 07 '18 at 11:06

2 Answers2

1

Sets are unordered in Python. You should not expect consistency.

For a simple example, at the REPL for Python3 (python -i),

>> x={3,1,2}
>>> print(x)
{1, 2, 3}

And similarly with Python2

>>> x={3,2,1}
>>> print(x)
set([1, 2, 3])

Nor are they simply autosorted, as in this Python3 example:

>>> x={3,('a','b'), 'x',0.11,'y',None, 'z',4.11,('c','d')}
>>> print(x)
{0.11, 3, 'y', 4.11, ('c', 'd'), 'x', ('a', 'b'), None, 'z'}

If you want them to stay in the inserted order, use an OrderedSet like this or just reuse OrderedDict.

Joshua Fox
  • 18,704
  • 23
  • 87
  • 147
0

Because by definition a set is an unordered pair. If you want them ordered use a list.

Just replace:

{'A', 'B'}

with:

['A', 'B']

This is because sets are created using curly braces {} and lists are defined using brackets []

Jab
  • 26,853
  • 21
  • 75
  • 114