Why do many examples use fig, ax plt.subplots
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
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.
Related reading
- Why do we flatten the data before we feed it into tensorflow?
- Why do we have to normalize the input for an artificial neural network?
- Why do we maximize variance during Principal Component Analysis?
- Why do we normalize the image to mean0.5, std0.5?
- Why do people write "#!/usr/bin/env python" on the first line of a Python script?
- Why do people write /usr/bin/env python on the first line of a Python script?
- Why does decreasing K in K-nearest-neighbours increase complexity?
- Why does my ROC curve look like a V?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.