0

Why doesn't the walrus operator pass the keyword argument figsize to matplotlib.pyplot.figure in this code?

#TODO: visualize whether the index is a valid x_value
fontsize=21
plt.figure(figsize:=(8,8))
plt.scatter(x_values_theory, y_values_theory, label='Theory')
plt.scatter(x_values_experimental, y_values_experimental, label='Experiment')
plt.xlabel('xlabel', fontsize=fontsize)
plt.ylabel('ylabel', fontsize=fontsize)
plt.legend(fontsize=fontsize)
plt.tick_params(labelsize=fontsize)
plt.show()

yields

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-55-94183c23eb8f> in <module>
      1 #TODO: visualize whether the index == df.[time
      2 fontsize=21
----> 3 plt.figure(figsize:=(8,8))
      4 plt.scatter(x_values_theory, y_values_theory, label='Theory')
      5 plt.scatter(x_values_experimental, y_values_experimental, label='Experiment')

/usr/local/lib/python3.8/site-packages/matplotlib/pyplot.py in figure(num, figsize, dpi, facecolor, edgecolor, frameon, FigureClass, clear, **kwargs)
    649             num = allnums[inum]
    650     else:
--> 651         num = int(num)  # crude validation of num argument
    652 
    653     figManager = _pylab_helpers.Gcf.get_fig_manager(num)

TypeError: int() argument must be a string, a bytes-like object or a number, not 'tuple'
Dan Getz
  • 7,743
  • 6
  • 29
  • 60
Tim Tyree
  • 9
  • 1

1 Answers1

3

Keyword arguments are specified with =, not :=. Per the PEP:

The := operator may be used directly in a positional function call argument; however it is invalid directly in a keyword argument.

So that means

plt.figure(figsize:=(8,8))

is equivalent to

figsize = (8,8)
plt.figure(figsize)

So your code ought to work if you just use the right operator:

plt.figure(figsize=(8,8))

If you want to both assign and pass a keyword argument at the same time, you need to write both of those things, for example:

plt.figure(figsize=(figsize:=(8,8)))

Note that the parentheses are required.

Dan Getz
  • 7,743
  • 6
  • 29
  • 60
  • I feel we've gone down a slippery slope, why write `figsize=(figsize:=(8,8))` when `figsize:=(8,8)` will do? – Tim Tyree Aug 25 '20 at 02:42
  • @TimTyree it won't do, as you saw when you tried it. Are you asking why the Python language isn't different? – Dan Getz Aug 25 '20 at 02:44
  • 1
    @TimTyree: Then you'd need awkward workarounds to *not* pass keyword arguments with `:=`. – user2357112 supports Monica Aug 25 '20 at 02:46
  • 1
    Python has generally followed a design of making things explicit instead of implicit. Local variable names aren't automatically matched up with anything but themselves. If you want to pass a local variable to a keyword argument, or a dictionary key, of the same name, you have to write both: the local variable name, and the key name. If they happen to be the same, then you say that by writing them both the same. So it doesn't surprise me that they didn't change this when they added the `:=` operator. – Dan Getz Aug 25 '20 at 02:52