2

I have a function in my code that takes an Axes-instance to plot on. I want to set the default to be the current axis. This leads to the followig code:

from matplotlib import pyplot as plt

def plotfunc(ax=plt.gca()):
    # Here I would usually plot some functions on ax
    return True

plt.figure()
plt.show()

What I would expect from this script is one blank figure showing up. But what I get is one figure and another empty subplot, although I din't even call plotfunc. The additional subplot doesn't appear when I delete the "=plt.cga()" part in the code. Is there a way to set pltgca() as the standard axis for plotfunc without getting another subplot?

I'm using python 3.6 under Ubuntu 18.04.1.

  • 1
    Your question is a special case of the ["Least astonishment"](https://stackoverflow.com/questions/1132941/least-astonishment-and-the-mutable-default-argument) canonical, but I figured it's significantly different at its core so I decided to add an answer. It's worth reading the question and top answers there, because it helps you understand how default keyword arguments work in python. – Andras Deak -- Слава Україні Oct 24 '18 at 15:11

2 Answers2

1

In python default keyword arguments to a function are set during definition of the function (as opposed to call time). So what happens when you run that script is:

  1. the import is executed
  2. plotfunc is defined -> plt.gca() is executed and the return value is bound to the default value of ax
  3. plt.figure() is executed
  4. plt.show() is executed

Even though the function is never called, the default keyword argument is set and a corresponding Axes (and figure) is created. Then plt.figure() explicitly creates a new figure, the second one you see.

You should set a sentinel value to ax, as in ax=None, then override if ax is None: ax = plt.gca() inside the function which only happens on a function call.

0

The usual way to allow for an axes to be supplied to a function and fall back to the "current axes" if none is given would be

def plotfunc(ax=None):
    ax = ax or plt.gca()
    # plot something to ax
    ax.plot(...)
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712