# 4.7. Sequence Unpacking

## 4.7.1. Unpacking Values

a = 1
a, b = 1, 2
a, b, c = 1, 2, 3

a, b, c = 1, 2, 3
a, b, c = (1, 2, 3)

a, b, c = (1, 2, 3)
a, b, c = [1, 2, 3]
a, b, c = {1, 2, 3}

(a, b, c) = (1, 2, 3)
(a, b, c) = [1, 2, 3]

[a, b, c] = [1, 2, 3]
[a, b, c] = (1, 2, 3)

{a, b, c} = {1, 2, 3}
# SyntaxError: can't assign to literal


Note

Note, that set is unordered collection

### 4.7.1.1. Too many values to unpack

a, b, c = [1, 2, 3, 4]
# ValueError: too many values to unpack (expected 3)


### 4.7.1.2. Not enough values to unpack

a, b, c, d = [1, 2, 3]
# ValueError: not enough values to unpack (expected 4, got 3)


## 4.7.2. Unpacking arbitrary number of arguments

### 4.7.2.1. Unpacking values at the right side

a, b, *c = [1, 2, 3, 4]

a               # 1
b               # 2
c               # [3, 4]


### 4.7.2.2. Unpacking values at the left side

*a, b, c = [1, 2, 3, 4]

a               # [1, 2]
b               # 3
c               # 4


### 4.7.2.3. Unpacking values from both sides at once

a, *b, c = [1, 2, 3, 4]

a               # 1
b               # [2, 3]
c               # 4


### 4.7.2.4. Cannot unpack from both sides at once

*a, b, *c = [1, 2, 3, 4]
# SyntaxError: two starred expressions in assignment


### 4.7.2.5. Unpacking from variable length

a, *b, c = [1, 2]

print(a)        # 1
print(b)        # []
print(c)        # 2

a, *b, c = [1,]
# ValueError: not enough values to unpack (expected at least 2, got 1)


## 4.7.3. Naming convention

first, *middle, last = [1, 2, 3, 4]

first           # 1
middle          # [2, 3]
last            # 4

first, second, *others = [1, 2, 3, 4]

first           # 1
second          # 2
others          # [3, 4]

first, second, *others = range(10)

first           # 0
second          # 1
others          # [2, 3, 4, 5, 6, 7, 8, 9]

line = 'Apollo11,Twardowski,Watney,Ivanovic'

mission, *members = line.split(',')

mission         # Apollo11
members         # ['Twardowski', 'Watney', 'Ivanovic']

line = '5.4,3.9,1.3,0.4,setosa'

*features, label = line.split(',')
avg = sum(features) / len(features)

label           # 'setosa'
avg             # 2.75


## 4.7.4. Omitting values

• _ is regular variable name, not a special Python syntax

• _ by convention is used for data we don't want to access in future

line = 'Jan,Twardowski'

a, _ = line.split(',')

a, _, _ = 1, 2, 3

print(a)        # 1

_, interesting, _ = 1, 2, 3

print(interesting)  # 2

line = '4.9,3.1,1.5,0.1,setosa'

*_, label = line.split(',')

label           # setosa

line = 'twardowski:x:1001:1001:Jan Twardowski:/home/twardowski:/bin/bash'

username, _, _, _, full_name, *_ = line.split(':')

full_name       # Jan Twardowski

line = 'twardowski:x:1001:1001:Jan Twardowski:/home/twardowski:/bin/bash'

username, *_, home, _ = line.split(':')

home            # /home/twardowski


## 4.7.5. Using in a loop

DATA = [
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(5.7, 2.8, 4.1, 1.3, 'versicolor'),
]

for *features, label in DATA:
avg = sum(features) / len(features)
print(label, avg)

# virginica 3.875
# setosa 2.55
# versicolor 3.475

DATA = [
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(5.7, 2.8, 4.1, 1.3, 'versicolor'),
]

for *_, label in DATA:
print(label)

# virginica
# setosa
# versicolor


## 4.7.6. Assignments

### 4.7.6.1. Unpacking from sequence

• Complexity level: easy

• Lines of code to write: 1 lines

• Estimated time of completion: 3 min

English
1. Split input data (see below) by white space

2. Separate ip address and host names

3. Use asterisk * notation

Polish
1. Podziel dane wejściowe (patrz sekcja input) po białych znakach

2. Odseparuj adres ip i nazw hostów

3. Skorzystaj z notacji z gwiazdką *

Input
INPUT = '10.13.37.1      nasa.gov esa.int roscosmos.ru'

Output
ip: str
# 10.13.37.1

hosts: list
# ['nasa.gov', 'esa.int', 'roscosmos.ru']


### 4.7.6.2. Unpacking from nested sequence

English
1. For input data (see below)

3. Use asterisk * notation

Polish
1. Dla danych wejściowych (patrz sekcja input)

2. Oddziel nagłówek i rekordy

3. Skorzystaj z konstrukcji z gwiazdką *

Input
INPUT = [
('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species'),
(5.8, 2.7, 5.1, 1.9, 'virginica'),
(5.1, 3.5, 1.4, 0.2, 'setosa'),
(5.7, 2.8, 4.1, 1.3, 'versicolor'),
(6.3, 2.9, 5.6, 1.8, 'virginica'),
(6.4, 3.2, 4.5, 1.5, 'versicolor'),
(4.7, 3.2, 1.3, 0.2, 'setosa'),
(7.0, 3.2, 4.7, 1.4, 'versicolor'),
(7.6, 3.0, 6.6, 2.1, 'virginica'),
(4.9, 3.0, 1.4, 0.2, 'setosa'),
(4.9, 2.5, 4.5, 1.7, 'virginica'),
(7.1, 3.0, 5.9, 2.1, 'virginica'),
(4.6, 3.4, 1.4, 0.3, 'setosa'),
(5.4, 3.9, 1.7, 0.4, 'setosa'),
(5.7, 2.8, 4.5, 1.3, 'versicolor'),
(5.0, 3.6, 1.4, 0.3, 'setosa'),
(5.5, 2.3, 4.0, 1.3, 'versicolor'),
(6.5, 3.0, 5.8, 2.2, 'virginica'),
(6.5, 2.8, 4.6, 1.5, 'versicolor'),
(6.3, 3.3, 6.0, 2.5, 'virginica'),
(6.9, 3.1, 4.9, 1.5, 'versicolor'),
(4.6, 3.1, 1.5, 0.2, 'setosa'),
]

Output
header: tuple
# ('Sepal length', 'Sepal width', 'Petal length', 'Petal width', 'Species')

data: list
# [
#   (5.8, 2.7, 5.1, 1.9, 'virginica'),
#   (5.1, 3.5, 1.4, 0.2, 'setosa'),
#   (5.7, 2.8, 4.1, 1.3, 'versicolor'),
#   ...
# ]