DEV Community

Super Kai (Kazuya Ito)
Super Kai (Kazuya Ito)

Posted on • Edited on

Unpacking in Python (3)

Buy Me a Coffee

*Memo:

  • My post explains the unpacking with a for statement (2).
  • My post explains the unpacking with an assignment statement (1).
  • My post explains the unpacking with an assignment statement (2).
  • My post explains the iterable unpacking with * and a function (1).
  • My post explains the iterable unpacking with * and a function (2).
  • My post explains the dictionary unpacking with ** within a dictionary and function.

Iterable unpacking can be done without * and with a for statement as shown below:

*Memo:

  • The syntax of the one or more variables and commas(,), tuples(()) and/or lists([]) with in iterable is an iterable unpacking:
    • for v, in [[0]]: and for v in [[0]]: are different.
    • One or more variables and commas are a tuple even if () isn't used.
    • Lists are converted to tuples if lists are explicitly used on the left side of =:
  • The number of variables must match the number of the elements in each iterable in an iterable unless a *variable is used on the left side of =:
    • Only one *variable can be used within each tuple and list on the left side of = to flexibly accepts the zero or more elements of an iterable:
    • A *variable is the list whose default value is [] so the type is list.
    • A *variable cannot be used outside any list and tuple.
  • One or more *iterables can be used within each list, tuple and set within a list, tuple or set on the right side of = to unpack iterables:
    • One or more *iterables except str cannot be used outside each list, tuple and set within a list, tuple or set.
    • A *iterable cannot be used outside any list, tuple and set.
  • The one or more *iterables can be used as the arguments within a function call including print() to unpack into the one or more parameters including args but excluding *kwargs within a function definition:
    • One or more *iterables can be used with print() and *args but not with **kwargs.
  • One or more **dictionaries can be used within each dictionary within a list, tuple or set on the right side of = to unpack dictionaries:
    • A **dictionary cannot be used outside any dictionary, list, tuple and set.
  • A * is called an iterable unpacking operator to unpack an iterable as the name suggests so the one or more *iterables used within each list, tuple and set within a list, tuple or set on the right side of = and used as the arguments within a function call including print() to unpack iterables are iterable unpacking operators but the only one *variable used within each tuple and list on the left side of = to flexibly accepts the zero or more elements of an iterable isn't an iterable unpacking operator:
    • The iterable unpacking operator * can unpack(flat) only the most outer dimension of an iterable.
  • A ** is called a dictionary unpacking operator to unpack a dictionary as the name suggests so the one or more **dictionaries used within each dictionary within a list, tuple or set on the right side of = to unpack dictionaries are dictionary unpacking operators:
    • The dictionary unpacking operator ** can unpack(flat) only the most outer dimension of a dictionary.
  • The doc explains for statement.
for v1, v2, v3 in [[0, 1, 2], [3, 4, 5]]:              # list(list)
# for v1, v2, v3 in ((0, 1, 2), (3, 4, 5)):            # tuple(tuple)
# for v1, v2, v3 in iter([iter([0, 1, 2]),             # iterator(iterator)
#                         iter([3, 4, 5])]):
# for v1, v2, v3 in ['012', '345']:                    # list(str)
# for v1, v2, v3 in [range(3), range(3, 6)]:           # list(range)
    print(v1, v2, v3)
# 0 1 2
# 3 4 5

for v1, v2, v3 in {frozenset({0, 1, 2}),               # set(frozenset)
                   frozenset({3, 4, 5})}:
# for v1, v2, v3 in frozenset({frozenset({0, 1, 2}),   # frozenset(frozenset)
#                              frozenset({3, 4, 5})}):
    print(v1, v2, v3)
# 3 4 5
# 0 1 2

for v1, v2, v3 in [{0:1, 2:3, 4:5},                    # list(dict)
                   {6:7, 8:9, 10:11}]:
# for v1, v2, v3 in [{0:1, 2:3, 4:5}.keys(),           # list(dict.keys())
#                    {6:7, 8:9, 10:11}.keys()]:
    print(v1, v2, v3)
# 0 2 4
# 6 8 10

for v1, v2, v3 in [{0:1, 2:3, 4:5}.values(),           # list(dict.values())
                   {6:7, 8:9, 10:11}.values()]:
    print(v1, v2, v3)
# 1 3 5
# 7 9 11

for v1, v2, v3 in [{0:1, 2:3, 4:5}.items(),            # list(dict.items())
                   {6:7, 8:9, 10:11}.items()]:
    print(v1, v2, v3)
# (0, 1) (2, 3) (4, 5)
# (6, 7) (8, 9) (10, 11)

for v1, v2, v3 in {'012':'345', '678':'9AB'}:          # dict
# for v1, v2, v3 in {'012':'345', '678':'9AB'}.keys(): # dict.keys()
    print(v1, v2, v3)
# 0 1 2
# 6 7 8

for v1, v2, v3 in {'012':'345', '678':'9AB'}.values(): # dict.values()
    print(v1, v2, v3)
# 3 4 5
# 9 A B

for v1, v2 in {'012':'345', '678':'9AB'}.items():      # dict.items()
    print(v1, v2)
# 012 345
# 678 9AB

for v1, v2, v3 in [b'012', b'345']:                    # list(bytes)
# for v1, v2, v3 in [bytearray(b'012'),                # list(bytearray)
#                    bytearray(b'345')]:
    print(v1, v2, v3)
# 48 49 50
# 51 52 53

for v1, v2, v3 in {b'012':b'345', b'678':b'9AB'}:      # dict
# for v1, v2, v3 in {b'012':b'345',                    # dict.keys()            
#                    b'678':b'9AB'}.keys():
# for v1, v2, v3 in {b'012':bytearray(b'345'),         # dict                 
#                    b'678':bytearray(b'9AB')}:
# for v1, v2, v3 in {b'012':bytearray(b'345'),         # dict.keys()
#                    b'678':bytearray(b'9AB')}.keys():
    print(v1, v2, v3)
# 48 49 50
# 54 55 56

for v1, v2, v3 in {b'012':b'345',                      # dict.values()
                   b'678':b'9AB'}.values():
# for v1, v2, v3 in {b'012':bytearray(b'345'),         # dict.values()
#                    b'678':bytearray(b'9AB')}.values():
    print(v1, v2, v3)
# 51 52 53
# 57 65 66

for v1, v2 in {b'012':b'345', b'678':b'9AB'}.items():  # dict.items()
    print(v1, v2)
# 012 345
# 678 9AB

for v1, v2 in {b'012':bytearray(b'345'),               # dict.items()
               b'678':bytearray(b'9AB')}.items():
    print(v1, v2)
# b'012' bytearray(b'345')
# b'678' bytearray(b'9AB')

for v1, v2, v3 in [[0, 1, 2], [3, 4, 5]]:
# for (v1, v2, v3) in [[0, 1, 2], [3, 4, 5]]:
# for [v1, v2, v3] in [[0, 1, 2], [3, 4, 5]]:
    print(v1, v2, v3)
# 0 1 2
# 3 4 5

for v1, v2 in [[0, [1, [2]]], [3, [4, [5]]]]:
# for (v1, v2) in [[0, [1, [2]]], [3, [4, [5]]]]:
# for [v1, v2] in [[0, [1, [2]]], [3, [4, [5]]]]:
    print(v1, v2)
# 0 [1, [2]]
# 3 [4, [5]]

for v1, (v2, v3) in [[0, [1, [2]]], [3, [4, [5]]]]:
# for v1, [v2, v3] in [[0, [1, [2]]], [3, [4, [5]]]]:
# for (v1, (v2, v3)) in [[0, [1, [2]]], [3, [4, [5]]]]:
# for [v1, [v2, v3]] in [[0, [1, [2]]], [3, [4, [5]]]]:
    print(v1, v2, v3)
# 0 1 [2]
# 3 4 [5]

for v, in [[0]]:
# for (v,) in [[0]]:
# for [v] in [[0]]:
    print(v)
# 0

# It's not an iterable unpacking.
for v in [[0, 1, 2], [3, 4, 5]]:
    print(v)
# [0, 1, 2]
# [3, 4, 5]

# It's not an iterable unpacking.
for v in [[0], [1]]:
    print(v)
# [0]
# [1]

for v1, v2, v3 in [[0], [1]]:
    pass
# ValueError: not enough values to unpack (expected 3, got 2)

for v1, v2, v3 in [[0, 1, 2, 3], [4, 5, 6, 7]]:
    pass
# ValueError: too many values to unpack (expected 3)

for v, in [[], []]:
    pass
# ValueError: not enough values to unpack (expected 1, got 0)

for v, in [0, 1]:
    pass
# TypeError: cannot unpack non-iterable int object
Enter fullscreen mode Exit fullscreen mode

Top comments (0)