Like its animal namesake, turtle is very, very slow. It is only ever used as an educational tool, to let the learners see in real time how their algorithm translates to the turtle's movements. It is thus, unfortunately, pointless to try to speed up the code where a turtle poops out an image pixel by excruciating pixel. To get it up to speed (hehe), better tooling is required.
Jean-François Puget made an excellent comparison of various ways to generate the Mandelbrot set in Python. Among them, there is code for using GPU, code for using compiled Python... I chose to show you the numpy method, i.e. using the tools that most intermediate Python programmers might be familiar with, without going overboard. numpy is a library that does array calculations outside Python, and is thus able to do them very, very fast. Also, I switched the display library to pillow, a popular image processing library. Together, numpy and pillow let you do this quite fast.
As you said you were new to coding, a lot of this might be a bit advanced, but I wanted to show how actual production code might solve this issue, poossibly inspire you to see what is possible. Also, given that you are messing with Mandelbrot, I suspect you might have sufficient basis in mathematics to intuitively grasp the array operations numpy is providing here, even if you are just starting coding.
# pip install pillow numpy
from PIL import Image
import numpy as np
# Adapted from https://gist.github.com/jfpuget/60e07a82dece69b011bb
def mandelbrot(cmin, cmax, width, height, maxiter):
"""
cmin: bottom left corner, as a complex number
cmax: top right corner, as a complex number
width: width of the resultant array
height: height of the resultant array
maxiter: maximum number of iterations
"""
# make the real axis as an array of shape (width)
real = np.linspace(cmin.real, cmax.real, width, dtype=np.float32)
# make the imaginary axis as an array of shape (height)
imag = np.linspace(cmin.imag, cmax.imag, height, dtype=np.float32) * 1j
# combine them into a complex array of shape (width, height)
c = real + imag[:, None]
# make the output array of the same shape, fill it with int zeroes
output = np.zeros(c.shape, dtype='uint16')
# and a z array of the same shape, fill it with complex zeroes
z = np.zeros(c.shape, np.complex64)
# do the mandelbrotty thing:
for i in range(maxiter):
# make a bool array of the same shape showing where `z` is within range
notdone = np.less(z.real * z.real + z.imag * z.imag, 4.0)
# at the places where `notdone` is true,
# update the current iteration number;
# the places where `z` got out of range will be unaffected
output[notdone] = i
# update `z` in those same places
z[notdone] = z[notdone] ** 2 + c[notdone]
# make the center zero for nice contrast
output[output == maxiter-1] = 0
return output
cmin, cmax = -2-1j, 1+1j
width, height = 800, 600
maxiter = 80
# calculate the mandelbrot set
m = mandelbrot(cmin, cmax, width, height, maxiter)
# calculate the greyscale pixels
pixels = (m * 255 / maxiter).astype('uint8')
# make the greyscale image
img = Image.fromarray(pixels, 'L')
# and let us see it
img.show()
It takes my Macbook Pro 23ms to generate the mandelbrot array and then the image with the same parameters as yours.
numpyand related to assist with vector-like calculations.