Matplotlib is does not plot functions, but rather points. Of course any continuous function can be approximated by points if they are only dense enough.
The problem indeed occurs when zooming into the plot, in which case formerly dense points will spread out and a polygonial structure will be observable. Inversely when zooming out, it may happen that the function has not been evaluated outside a specific range and hence the plot will stay mostly empty.
A solution is to evaluate the function each time the axis limits change, notably on a grid which covers the complete axis range and has as many points as there are pixels. We can find out the number of pixels from the figure size and dpi.
To show the effect, I added a sinusodial function with a low amplitude here.
import numpy as np
import matplotlib.pyplot as plt
func = lambda x: (2*x)**2 + 2*x + -4 + 0.2*np.sin(x*20)
fig, ax = plt.subplots()
ax.axis([-8,8,-100,400])
line, = ax.plot([])
def update(evt=None):
xmin,xmax = ax.get_xlim()
npoints = fig.get_size_inches()[0]*fig.dpi
x = np.linspace(xmin, xmax, npoints)
y = func(x)
line.set_data(x,y)
fig.canvas.draw_idle()
ax.callbacks.connect('xlim_changed', update)
fig.canvas.mpl_connect("resize_event", update)
plt.show()
