0
  • How are *zip and *D.items() working in the following code?
  • What does * operator do?
import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(*zip(*D.items()))
plt.show()
miken32
  • 42,008
  • 16
  • 111
  • 154

2 Answers2

1

The asterisk operator as it relates to your code:

  • An iterable is something that can be iterated though
  • * unpacks an iterable
  • D.items() creates a dict_items object, a list of tuples. See .items() and dictionary view objects
    • dict_items([('Label1', 26), ('Label2', 17), ('Label3', 30)])
  • The * in zip(*D.items()), unpacks the dict_times object, and zip, aggregates elements from each of the iterables.
    • ('Label1', 'Label2', 'Label3')
    • (26, 17, 30)
    • zip creates a generator (another iterable), like <zip at 0x1c9f2248e00>, which is an iterable of tuples.
  • The * in *zip unpacks the generator, so the plot API has access to the two tuples.
import matplotlib.pyplot as plt

D = {u'Label1':26, u'Label2': 17, u'Label3':30}
plt.bar(*zip(*D.items()))

enter image description here

The asterisk operator in broader terms:

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
1

I would like to add to @TrentonMcKinney's answer some examples of how unpacking with * works:

>>> l = [1, 2, 3]
>>> print(l)  # == print([1, 2, 3])
[1, 2, 3]
>>> print(*l)  # == print(1, 2, 3)
1 2 3

Basically print(l) was converted to print([1, 2, 3]) and then the output was the list itself [1, 2, 3]. On the other hand, print(*l) was converted to print(1, 2, 3), this is, the list was unpacked an each element was passed as a separate argument to print, so the output was 1 2 3.

So in your example, the inner * is unpacking each of the items tuples (('Label1', 26), ('Label2', 17) and ('Label3', 30)) and passing them as a separate arguments to zip (zip(('Label1', 26), ('Label2', 17), ('Label3', 30))). That returns another list-like object equivalent to trasposing those sequences, this is, groups all the first elements of every iterable together, the second elements together, ... ([('Label1', 'Label2', 'Label3'), (26, 17, 30)]). The outter * unpacks them out of the list-like object to pass each tuple to the plt.bar function(plt.bar(('Label1', 'Label2', 'Label3'), (26, 17, 30))).

Similar to * to unpack sequences, there is a ** that is used to unpack mappings into keyword arguments. f(**{'a': 1, 'b': 2}) is the same as f(a=1, b=2).

Adirio
  • 5,040
  • 1
  • 14
  • 26