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

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 = '4.9,3.1,1.5,0.1,setosa'

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

features         # ['4.9', '3.1', '1.5', '0.1']
label            # 'setosa'
line = 'astronauts,twardowski,watney,ivanovic'

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

group_name      # astronauts
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(':')

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

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

username        # twardowski
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:
    print(features)

# [5.8, 2.7, 5.1, 1.9]
# [5.1, 3.5, 1.4, 0.2]
# [5.7, 2.8, 4.1, 1.3]
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

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)

  2. Separate header and records

  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'),
#   ...
# ]