The Pyplot API vs Object-Oriented API
Matplotlib's pyplot module is a state machine: it keeps a "current figure" and a "current axes" in module-level state, and functions like plt.plot and plt.title act on whatever is current. It is compact for one-off plots. The object-oriented API makes the Figure and Axes objects explicit and passes them to methods. Both drive the same engine; the difference is where the state lives - in the module, or in your variables.
The State-Machine Pitfall
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [1, 4, 9]) # figure 1, axes 1
plt.title("figure one")
plt.plot([1, 2, 3], [9, 4, 1]) # still figure 1! a second line
plt.title("figure two") # overwrote the first title
plt.figure() # now figure 2
plt.plot([1, 2, 3], [0, 1, 2])
plt.title("figure two, really")
plt.show()
The second plt.plot went to figure 1 because no new figure had been requested, and the title was replaced rather than applied to a new chart. With three or more figures the "which chart am I configuring?" question becomes a bug factory - this is the failure mode that makes the OO style the default for anything real.
The OO Pattern
import matplotlib.pyplot as plt
fig1, ax1 = plt.subplots()
ax1.plot([1, 2, 3], [1, 4, 9])
ax1.set_title("figure one")
fig2, ax2 = plt.subplots()
ax2.plot([1, 2, 3], [9, 4, 1])
ax2.set_title("figure two")
plt.show() # both figures, unambiguous
Every method call names its target: ax1.plot, ax2.set_title. There is no current state to be wrong about, and the two figures can be interchanged, reordered, or saved independently. Subplots make the pattern stronger still: fig, (ax1, ax2) = plt.subplots(1, 2) gives you two Axes objects to configure in any order.
When Pyplot Is Fine
- Quick exploratory plots in a notebook - one figure, a few lines, thrown away.
- Script-level boilerplate:
plt.show(),plt.close(),plt.rcParams- these module functions are still the interface even in OO code. - Reading code written by others - most tutorials and StackOverflow answers use pyplot, and
plt.plotis exactlygca().plot.
Translation Table
| pyplot | Object-oriented |
|---|---|
plt.plot(x, y) | ax.plot(x, y) |
plt.title(t) | ax.set_title(t) |
plt.xlabel(s) | ax.set_xlabel(s) |
plt.xlim(a, b) | ax.set_xlim(a, b) |
plt.legend() | ax.legend() |
plt.tight_layout() | fig.tight_layout() |
plt.savefig(p) | fig.savefig(p) |
One asymmetry: figure-level operations (layout, saving, suptitle) belong to the Figure even in the OO style, and plt.show() remains the display call.
Summary
pyplot is a state machine that is convenient for one chart and a source of bugs for many; the OO style binds each operation to an explicit Axes and scales without ambiguity. The habit to build: create figures with plt.subplots(), keep the fig and ax objects, and call methods on them - reserving pyplot for show, close, and rcParams.