====== Unpacking Sequences ======
Sequences can be explicitly/implicitly //unpacked// into discrete, ordered units of some type. Unpacking happens automatically using the '','' (comma). (The syntax is also used for [[python3_tuples|Tuple]] construction.)
Unpacking works //only// in instances where the number of variables used //exactly// matches the number of items in the sequence.
**Note:** In the below examples parenthesis are not required, and are included for clarity.
=====Implicit Unpacking: Member Assignment=====
The most common application of unpacking is to (shallow) copy items into named variables.
====Lists====
Unpacking a [[python3_lists|List]].
>>> seq = [1, 2, 3]
>>> (a, b, c) = seq # a=1, b=2, c=3
====Tuples====
Unpacking a [[python3_tuples|Tuple]].
>>> tup = ('a', 'b')
>>> (x, y) = tup # x='a', y='b'
====Strings====
Unpacking the characters of a [[python3_strings|String]].
>>> (first, second, third) = "abc" # first='a', second='b', third='c'
=====Input (Console, File)=====
Since ''input()'' is done a line at a time (and returns [[python3_strings|string]] data), unpacking is idiomatic Python3 for many input operations.
The below examples use the [[python3_strings|string]] ''split()'' method and the [[python3_functional|functional]] tool ''map()''.
>>> (x, y) = input().split() # x='a', y='b' on input "a b"
>>> (x, y) = map(int, input().split()) # x=1, y=2 on input "1 2"
=====In-Place Swap/Mutual Replacement=====
Swapping objects.
>>> x = 1
>>> y = 2
>>> (x, y) = (y, x) # x=2, y=1
=====Explicit Unpacking: The * (Star) Operator=====
The unary ''*'' (star) operator is used to explicitly indicate unpacking, often outside the context of assignment. Use is common when elements of a sequence are intended to be used as the parameters to a function.
E.g., (Assume that ''seq'' contains 3 elements) ''fun(seq[0], seq[1], seq[2])'' could be rephrased more tersely as ''fun(*seq)''.
====Unpacking Arguments====
Consider printing values in a [[python3_lists|List]].
>>> print([1, 2, 3]) # legal, but performs a cast str([1, 2, 3])
[1, 2, 3]
In many instances we may wish to print a list's elements, but not formatted as a Python3 ''list''.
>>> print(*[1, 2, 3]) # as though we indexed each individually
1 2 3
====Extended Iterable Unpacking====
Extended Iterable Unpacking (([[https://www.python.org/dev/peps/pep-3132/|PEP 3132]] - Extended Iterable Unpacking)) extends unpacking to allow sequences on the left hand side of an assignment.
Like regular unpacking for member assignment, extended iterable unpacking is ''only'' allowed in instances where the Python3 interpreter can infer the number and position of arguments.
Note that the following examples make use of Python3 [[python3_ranges|range()]] objects.
===Unpacking First and Rest===
>>> (first, *rest) = list(range(1, 10)) # first=0, rest=[1, 2, ..., 9]
===Unpacking Rest and Last===
Note that the ''*rest'' as a second element in the previous example is somewhat arbitrary depending on need.
It is also valid to start with the iterable.
>>> (*rest, last) = list(range(1, 10)) # rest=[0, 1, ..., 8], last=9
===Unpacking First, Rest, and Last===
One or more additional named variables can be specified //before// or //after// the ''rest''.
>>> (first, *rest, last) = list(range(1, 10)) # first=0, rest=[2, 3, ..., 8], last=9
===Empty Iterables===
Note that the catch-all nature of a starred member does not mean that these values are required. In the event where additional elements are omitted they are treated as an empty sequence.
>>> (first, second, *rest) = [1, 2] # first=1, second=2, rest=[]
The number of named elements before and after ''*rest'' is arbitrary as long as those elements do not include additional starred iterables.(((fst, *rest1, mid, *rest2, last) = list(range(1, 10%%))%% would result in ''SyntaxError: two starred expressions in assignment'' because it is unknown how many items would be in ''rest1'' and '''rest2'''. In this instance prefer list slicing.))