I am quite used to unpacking sequences in Python like:
my_tuple = (1, 2, 3)
a, b, c = my_tuple
I have noticed that I can also do it with sets:
my_set = set((1, 2, 3))
a, b, c = my_set
Why can I do this? I mean, it makes perfect sense for lists and tuples which are ordered. But how does this make sense for a set which is not ordered?
How can I be sure which value ends up in which variable on the left-hand side? Or maybe I do not quite understand ordered vs. unordered?
a,b,c = set((3,2,1))
Here a==1
, b==2
, and c==3
illustrates what I mean is ambiguous.
14
You need to distinguish between the set, which has no ordering, and the set iterator, which has an arbitrary order derived from the underlying hash values of the set. a, b, c = some_set
is really a, b, c = iter(some_set)
in disguise.
>>> type({1,2,3})
<class 'set'>
>>> type(iter({1,2,3}))
<class 'set_iterator'>
I think you have the wrong expectations about what “unordered” means.
A set clearly has some order – you can iterate over it, convert it to a list, and, as you’ve seen, unpack it. Moreover, given the same elements and the same Python version, the set will always have the same order.
This doesn’t mean you can assume anything about a set’s order. Specifically, the unpacking example you shared is a very bad idea. You’ll clearly get a
, b
and c
populated with the elements of the set, but you can’t make any assumptions on which variable will get which value. If it doesn’t matter, by all means, go for it. If it does, you should use some ordered collection (such as a list), or explicitly handle sorting them.
In Python 3.12 if you run:
my_set = set((3, 2, 1))
a, b, c = my_set
print(a, b, c)
The result is always the same 1 2 3
. This is due to how the current internal implementation of Python works for small integers. (I remember that it was different in previous versions.) This behavior is not reliable and may change in the future. Sets should be treated as unordered.
For another example, if you run:
my_set = set(('text3', 'text3', 'text1'))
a, b, c = my_set
print(a, b, c)
What will be printed will be different each time.
If you want them to maintain the order, you could, for example, sort them first:
a, b, c = sorted(my_set)
Why unpacking sets
Unpacking sets can have different use cases in function arguments, set operations, and more. Here are some examples:
- Function arguments
def add(a, b, c):
return a + b + c
numbers = {1, 2, 3}
result = add(*numbers)
- Combining Sets and other iterables
set1 = {1, 2, 3}
list1 = [4, 5, 6]
combined = [*set1, *list1]
There are many other use cases as well.
You can unpack any iterable object, here some examples
a, b, c = "abc"
a, b, c = iter("abc")
The previous cases are order preserving.
What happen with a set
which is not ordered?
s = set("abc")
print(s)
# {'c', 'b', 'a'}
a, b, c = s
print(a, b, c)
# c b a
The simultaneous initialization of the variables follow the “internal” order of the data structure.