If you want to clear the entire the entire axes you can do
ax.cla()
however that will also do things like rest the limits, tickers, etc
If you want to remove just the lines (or any of the other named Artists):
# PR linked above makes list unnecessary
for art in list(ax.lines):
art.remove()
I would also encourage programming styles where you do capture and track the individual artists when you create them, but I know that is not always easy. It is not an unfair case to say the Axes has them so why should the user also track them!
Is this something that you do often? I am becoming a bit worried that we have underestimated how well used the lines / collections / patches / … attributes are used.
On one hand, I am very wary of implementing part of some well know interface (it is pretty easy to make an API that is in the uncanny valley where it is enough like a well-known interface that it feels like it should “just work” but is enough different that you guess the behavior wrong half the time), on the other I think there is a case for these attributes keeping a clear or remove_all method.
The obvious ways to do this do lead to weird places (e.g. sub class tuple to add .clear() … but then ax1.lines.clear() works and ax2.lines.clear() works so should (ax2.lines + ax1.lines).clear() work? If not, tat is a bit awkward as for the most part we expect type-stability on +. If yes…you now are re-writing all of the __add__ methods now have to sort out what to do about (ax1.lines[:4] + ax2.lines).clear(). If no, that is a bit off because we expect (for the most part) type-stability on slicing and sensible type-promotion on +). If yes then now we end up also re-writing __getitem__ to make sure we return our sub-class in slice…
@tacaswell Thank you very much for your comprehensive answer!
Indeed
ax.cla()
is not what we usually want while your proposed for-loop looks good.
To clarify our use case: We mainly use this in the context of GUI or user interactions with a plot where it stays the same but its content changes. While I don’t know how widespread this is, the usage of lines etc. and even “wrong solutions” (in the future) for deleting them are very widespread if you search for something like “matplotlib remove all lines”. Another option one finds is
ax.lines = []
which is even worse and already stopped working with 3.5. (Which is indeed the reason I noticed the change.) After some research I found the fitting changelog entry which describes the change quite well but does not really outline its implications.
I totally unterstand the reasons for the change and why making lines.clear() still possible is not a good solution for you. But would it help to name it something like your proposed lines.remove_all() which internally is implemented as the for-loop? Naming it different than clear() at least I would not assume that something like (ax1.lines + ax2.lines).remove_all() is possible while clear() somehow implies that the underlying objects are lists.
I am worried that we may have to slow down our deprecation timeline on the list-like removals. I think they are more widely used than we thought and they were documented!