Why do many examples use fig, ax plt.subplots
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Many Matplotlib examples begin with fig, ax = plt.subplots() because that one line gives you explicit handles to the two main plotting objects. fig represents the whole figure, and ax represents one plotting area inside it. The pattern is popular not because it is stylistically trendy, but because it scales better than relying on the implicit global state in pyplot.
What fig and ax Actually Mean
A Matplotlib figure can contain many things: axes, titles, legends, colorbars, and layout settings. The axes object is the part that usually receives plotting commands such as lines, bars, labels, and limits.
In that example, ax.plot() draws on one specific axes. If the figure later had multiple subplots, the same pattern would still work cleanly because each axes object stays explicit.
Why Not Just Use plt.plot()
Matplotlib also offers a stateful style through pyplot.
That is fine for a quick script or a one-cell notebook example. The problem is that pyplot keeps track of a current figure and a current axes behind the scenes. Once the code grows, hidden state becomes harder to reason about.
With fig, ax = plt.subplots(), the target of each call is explicit. That makes the code easier to compose, reuse, and review.
The Object-Oriented Style Scales Better
The biggest advantage appears when you have more than one subplot.
This is much clearer than bouncing between plt.subplot(), plt.plot(), plt.title(), and whatever object pyplot happens to consider current at each step.
The style also makes layout concerns easier to separate. Figure-wide adjustments belong on fig, while data-specific settings belong on ax or axes.
It Works Better With Helper Functions
Reusable plotting functions are one of the strongest reasons to prefer the explicit object style. Instead of letting a helper reach into global plotting state, pass it the axes you want it to draw on.
That function can now draw into a single plot, a subplot grid, or a figure produced somewhere else. It is a much cleaner API than assuming a global current axes exists.
plt.subplots() Is Convenient, Not Verbose
Another reason the pattern survives in so many examples is that it is compact. One call creates both the figure and the axes in the most common configuration.
It also scales nicely when you need more control:
That single line creates a grid and returns the handles you need to work with it. You get the benefits of explicit objects without much setup cost.
One Subtlety: ax Might Be One Object or an Array
The return shape depends on how many subplots you ask for. A single subplot usually returns one axes object. Multiple subplots usually return an array of axes.
If you want fully predictable return shapes in utility code, squeeze=False can help.
This is a small detail, but it explains why some examples index axes[0] while others call methods directly on ax.
Common Pitfalls
- Treating
figandaxas interchangeable even though they represent different layers of the plotting model. - Mixing explicit axes-based calls with lots of implicit
pltstate changes in the same function. - Forgetting that
plt.subplots()may return a single axes or an array depending on the requested layout. - Writing helper functions that assume a global current axes instead of accepting one explicitly.
- Putting figure-wide operations such as layout adjustments on
axinstead offig.
Summary
- '
fig, ax = plt.subplots()creates explicit handles to the figure and the plotting area.' - The pattern avoids hidden
pyplotstate and scales better as code gets more complex. - It is especially useful for multi-axes layouts and reusable plotting helpers.
- '
figcontrols figure-level concerns, whileaxcontrols a specific subplot.' - The pattern is common because it is both clearer and still concise.

