@@ -950,6 +950,10 @@ def show(
950950 if not all (isinstance (t , str ) for t in title ):
951951 raise TypeError ("All titles must be strings." )
952952
953+ # Track whether the caller supplied their own axes so we can skip
954+ # plt.show() later (ax is reassigned inside the rendering loop).
955+ user_supplied_ax = ax is not None
956+
953957 # get original axis extent for later comparison
954958 ax_x_min , ax_x_max = (np .inf , - np .inf )
955959 ax_y_min , ax_y_max = (np .inf , - np .inf )
@@ -1273,8 +1277,11 @@ def _draw_colorbar(
12731277 # Default (show=None): display in non-interactive mode (scripts), suppress in interactive
12741278 # sessions. We check both sys.ps1 (standard REPL) and matplotlib.is_interactive()
12751279 # (covers IPython, Jupyter, plt.ion(), and IDE consoles like PyCharm).
1280+ # When the user supplies their own axes, they manage the figure lifecycle, so we
1281+ # default to not calling plt.show(). This allows multiple .pl.show(ax=...) calls
1282+ # to accumulate content on the same axes (see #362, #71).
12761283 if show is None :
1277- show = not hasattr (sys , "ps1" ) and not matplotlib .is_interactive ()
1284+ show = False if user_supplied_ax else ( not hasattr (sys , "ps1" ) and not matplotlib .is_interactive () )
12781285 if show :
12791286 plt .show ()
12801287 return (fig_params .ax if fig_params .axs is None else fig_params .axs ) if return_ax else None # shuts up ruff
0 commit comments