In this tutorial, you will learn to draw with the Python Turtle module. It’s a fun way to learn Python while discovering your creativity!
What is Python Turtle?
Python Turtle is a module that allows you to draw complex pictures and shapes using an x-y plane and rotations clockwise or anti-clockwise. It’s a fun way to start practicing programming in Python and it provides two interfaces: a procedural one and an object-oriented one.
We will draw several shapes using the Turtle module and by the end of this tutorial, you will be comfortable with it and with multiple Python constructs.
Let’s start drawing!
Basic Concepts about Python Turtle
Before drawing a shape we have to understand the basic concepts used by the Turtle module to draw.
Think about the x-y plane and imagine that there is a cursor at position (0, 0) pointing in the direction of the positive x-axis (position 1 in the picture below).
At this point, you can use a Turtle function to move the cursor in the direction it’s facing by a certain amount of pixels (position 2 in the picture below).
While moving, the cursor draws a line, so in this case, we would have a line that connects the points with coordinates (0,0) and (30,0).
You can identify the position of a point in the x-y plane by giving a specific value to x and y.
Now, if we want to draw a line in the direction of the y-axis, that starts at position (30,0) and it’s perpendicular to the x-axis, we have to rotate the cursor by 90 degrees anti-clockwise (position 3 in the picture below).
The Turtle module provides a way to do that before drawing the next line.
Once you change the direction of the cursor you can move the cursor forward and draw a second line (position 4).
Using this principle you can draw as many lines as you want and rotate the cursor using any angle you prefer.
Let’s start drawing the first shape…
Drawing a Square with Python Turtle
The first shape we will draw is a square that:
- Starts at (0,0).
- Is inside the 1st quadrant (positive x and y axis).
- Has a 200 pixels side.
from turtle import * color('red', 'yellow') begin_fill() forward(200) left(90) forward(200) left(90) forward(200) left(90) forward(200) end_fill() done()
Let’s go through the simple program above…
After importing the Turtle module we set the pencolor (for the border of the shape) and the fillcolor (to fill the shape) using the color() function.
Here you can see how pencolor and fillcolor are set when we call color() inside Python IDLE:
>>> from turtle import * >>> color('red', 'yellow') >>> pencolor() >>> 'red' >>> fillcolor() >>> 'yellow'
The functions begin_fill() and end_fill() are required before and after drawing a shape to be filled.
…what do they do?
The forward() function moves the turtle (the cursor) by the specified number of pixels in the direction the turtle is pointing to.
In this case, the turtle points by default in the direction of the positive x-axis so this command will move it by 200 pixels along the x-axis (in the 1st quadrant).
The left() function turns (or rotates) the turtle anti-clockwise by a certain angle that by default is expressed in degrees.
That’s why the second call to the forward() function draws a line perpendicular to the first one (90-degree angle) and in the 1st quadrant.
With the same logic, we can draw the four sides of a square.
Here is the output…
Code Refactoring Before Continuing
Before moving to the next shape I’d like to refactor the previous code that contains lots of repetition (not a good thing for code in any language)
We will create a function that we can use also when drawing other shapes.
from turtle import * def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('red', 'yellow') begin_fill() side_count = 0 while side_count < 4: pixels = 200 if side_count == 0: angle = 0 else: angle = 90 turn_and_draw(angle, pixels) side_count += 1 end_fill() done()
We have defined the function turn_and_draw() which first changes the direction of the turtle and then draws a line.
If we don’t want the turtle to turn (i.e. when we draw the first side of the square) we can pass 0 degrees as turn_angle (see the if-else statement inside the while loop).
Let’s see what the code looks like if we want to draw the square starting with the first side along the y-axis instead of the x-axis.
The only thing that changes is the if-else statement inside the while loop, which becomes:
... ... if side_count == 0: angle = 90 else: angle = 270 ... ...
That’s because to draw the first side we rotate 90 degrees anti-clockwise (remember that by default the turtle points in the direction of the positive x-axis).
Now, considering that in our function we use the Turtle function left() to rotate, we have to provide an angle of 270 degrees.
If you think about it…we have to rotate anti-clockwise across 3 quadrants to reach the position we want (the same applies to the three remaining sides).
Not ideal, have a look at how you could improve this function using also the right() Turtle function depending on what you need…
Draw a Triangle with Python Turtle
Let’s use the function we have created in the previous section to draw a triangle that starts at (0,0) and has all three sides of the same length (equilateral).
from turtle import * # Draw a triangle def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('blue', 'orange') begin_fill() side_count = 0 while side_count < 3: pixels = 200 if side_count == 0: angle = 0 else: angle = 120 turn_and_draw(angle, pixels) side_count += 1 end_fill() done()
You can see how handy is the function we have created in the previous section.
Simply by changing the value of the angle we can draw a triangle instead of a square.
The value 120 for the rotation angle is due to the fact that an equilateral triangle has three 60-degree angles (and 180 – 60 = 120).
This is the result of our creation 🙂
How to Draw a Star With Python Turtle
Now that we have seen how to draw two basic shapes, we will create something more complex.
We will draw a 5-point star!
You will see that actually, drawing a star has the same level of complexity as the other two programs we have seen so far for the square and the triangle.
That’s because the only two values we have to change are:
- The number of lines to draw (the number of times we execute our while loop).
- The angle between each line.
In a regular 5-point star the sum of the five angles is 180 degrees, so every angle will be 36 degrees.
Remember that for our rotation we will use 180 – 36 = 144.
Here is the code:
from turtle import * # Draw a star def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('green', 'blue') begin_fill() side_count = 0 while side_count < 5: pixels = 250 if side_count == 0: angle = 0 else: angle = 144 turn_and_draw(angle, pixels) side_count += 1 end_fill() done()
And here is our star…
To draw different types of stars we can simply update the:
- Condition of the while loop.
- Value of the angle in the else branch.
Here is what we get if we use the following:
... ... while side_count < 8: pixels = 250 if side_count == 0: angle = 0 else: angle = 162 turn_and_draw(angle, pixels) side_count += 1 ... ...
Drawing a More Complex Star
I would like to draw a symmetric star with a lot more points to create a more interesting effect.
Initially, we have considered doing that by simply changing the condition in the while expression of the previous code and considering a smaller angle between each side of the star.
But eventually, after a few attempts with different values, I realized that it wasn’t a viable approach.
Let’s try something different…
I want to draw a star with multiple points and use it as a condition to know that the star is complete the moment in which the turtle reaches the first point of the star, in this case, the origin of the x-y plane.
To do this we will use the pos() function that returns the current position of the turtle:
>>> pos() >>> (0.00,0.00)
Have a look at the following Python code for the while loop (the rest of the code doesn’t change):
... ... while abs(pos()) > 0.1 or side_count == 0: pixels = 250 if side_count == 0: angle = 0 else: angle = 162 turn_and_draw(angle, pixels) side_count += 1 ... ...
I have kept the same value for the angle but the logic of the while loop has changed.
This time we draw lines until either side_count == 0 (for drawing the first line) or the absolute value of pos() is bigger than 0.1.
Basically, we want to stop drawing lines once we have reached the origin again…
The reason why I have used the number 0.1 in the while condition instead of 0.0 is that I noticed that the absolute value of pos() is never zero when the origin is reached. It’s a very small number, but not zero.
Here is one of the numbers I got during my tests: 2.206117911819664e-13.
And now…drum roll…here’s what we have drawn:
Draw a Circle with Python Turtle
Drawing circles is also something you might want to learn in order to create more complex shapes with Turtle.
To do that the Turtle module provides the circle() function. This function is very easy to use, simply pass the radius of the circle as an argument:
from turtle import * # Draw a circle color('green', 'light blue') begin_fill() circle(100) end_fill() done()
You can also draw a partial circle by providing a second option argument (called extent) that is also an angle.
For example, to draw a semicircle we will give the extent the value 180.
The call to the circle function becomes:
And here is the semicircle:
It’s time to put all this knowledge into practice!
Draw a House with Python Turtle
A little coding challenge, let’s see if we can draw a house using Turtle.
If you think about it the principle is simple, we have to draw 7 lines and turn the turtle passing the right angle values before drawing each line.
Let’s give it a try…here is the result we want:
We will draw it using multiple calls to the turn_and_draw() function we have created before.
Also, we will start drawing the bottom part of the house from the usual position (0,0).
After a bit of tweaking, here is the code:
from turtle import * # Draw a house def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('red', 'red') begin_fill() turn_and_draw(0, 60) turn_and_draw(90, 75) turn_and_draw(270, 60) turn_and_draw(270, 75) turn_and_draw(90, 60) turn_and_draw(90, 90) turn_and_draw(270, 45) turn_and_draw(135, 190) turn_and_draw(90, 190) turn_and_draw(135, 45) turn_and_draw(270, 90) end_fill() done()
Try it on your IDE so you can have a clear idea about the way this is drawn.
And here is our house, not bad 🙂
I have a small challenge for you…
…try to refactor this code by using a Python for loop so you don’t have to repeat calls to turn_and_draw() multiple times.
Let me know if you have any questions about it 🙂
How to Draw a Rhombus with Python Turtle
As requested in the comments, I will show you how to draw a rhombus using Turtle.
It’s all about understanding which angles to apply when rotating the cursor before drawing.
The code we went through in the previous section to draw a house can be reused and can give you some ideas on how to draw a rhombus.
We will reuse the function turn_and_draw() to give the cursor the right directions to draw a rhombus.
Let’s start by drawing a rhombus in which all four angles are 90 degrees.
from turtle import * # Draw a rhombus def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('red', 'red') begin_fill() turn_and_draw(45, 150) turn_and_draw(90, 150) turn_and_draw(90, 150) turn_and_draw(90, 150) end_fill() done()
You can see from the Python code above that the first time we rotate the cursor by 45 degrees to start drawing the first side of the rhombus.
After that, every other rotation is 90 degrees until we complete drawing the rhombus.
Here is the result:
Now, how can you draw a rhombus where not all the angles are 90 degrees?
Note: Consider that the sum of the interior angles of a rhombus is 360 degrees.
from turtle import * # Draw a rhombus def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) color('red', 'red') begin_fill() turn_and_draw(60, 150) turn_and_draw(60, 150) turn_and_draw(120, 150) turn_and_draw(60, 150) end_fill() done()
Et voilà, here is the new rhombus:
Changing the Drawing Speed with Turtle
Before moving to the next section have a look at how you can change the drawing speed using the Turtle speed() function.
This function allows to set the speed to an integer value between 0 and 10. Here are some examples of values:
Before continuing try to set the speed to different values while you draw the house and notice the difference.
For example, for the fast speed add the following line at the beginning of your program (e.g. just before the color() function):
Express Your Creativity with Python Turtle
And now it’s the time to express your creativity with Turtle.
Let’s create multiple shapes of different colors using the examples covered in this tutorial.
We will draw the following:
- One 5-point star.
- Multiple circles inside each other and with a point in common.
- One complex star.
- A sequence of multiple isosceles triangles.
Considering that we want to draw a simple star first we will start from the code we have created for our first star.
But instead of using it the way it is, we will do some more refactoring to reduce duplication.
from from turtle import * # Draw a complex picture made of multiples shapes def turn_and_draw(turn_angle, draw_pixels): left(turn_angle) forward(draw_pixels) def draw_generic_shape(turn_angle, draw_pixels, num_of_sides): begin_fill() side_count = 0 while side_count < num_of_sides: pixels = draw_pixels if side_count == 0: angle = 0 else: angle = turn_angle turn_and_draw(angle, pixels) side_count += 1 end_fill() def draw_star(x, y, *colors): goto(x,y) color(*colors) draw_generic_shape(144, 250, 5) # Start drawing draw_star(0, 150, 'green', 'blue') done()
I have converted the part of the code that contains the while loop into a function called draw_generic_shape().
This function is called by the function draw_star() that before drawing moves the turtle to the position (x,y) using the goto() Turtle function.
Notice how the draw_star() function uses *colors to read the value of the colors to use. If you want to know more about it have a look at this article about *args and *kwargs in Python.
Now, let’s add a method to draw multiple circles:
def draw_circles(x, y, *colors): goto(x, y) color(*colors) begin_fill() for x in range(6): circle(x*25) end_fill()
This time instead of using a while loop we are using a Python for loop.
The code is self-explanatory.
Let’s run it, we will call the draw_circles() function with the following arguments:
draw_circles(0, 0, 'blue', 'yellow')
Notice how we have changed the value of y to make sure the circles don’t overlap with the star.
The Penup() and Pendown() Functions in Turtle
This is the drawing you will see when you run the code:
It looks good except for the fact that there is a connecting line between the star and the circles.
That’s because Turtle assumes that lines have to be drawn unless we tell it otherwise using the penup() function.
The penup() function pulls the pen up, this means that no line is drawn while the turtle moves. To go back to drawing Turtle provides the pendown() function.
We will add the penup() and pendown() function calls before and after the call to goto(x, y) in each function where is present.
For example, the draw_star() function becomes:
def draw_star(x, y, *colors): penup() goto(x,y) pendown() color(*colors) draw_generic_shape(144, 250, 5)
Before continuing run your code and confirm that the connecting lines between the shapes are not present anymore.
Adding a Complex Star to Our Composition
We will reuse the same values used before to draw the complex star.
So, create a new function called draw_complex_star(). We will make a small change in the while condition that detects when it’s time to stop drawing.
This change is based on the fact that this time we don’t start drawing the star from the position (0,0) in the way we have done in the previous example.
Here is the function:
def draw_complex_star(x, y, *colors): penup() goto(x,y) pendown() color(*colors) begin_fill() side_count = 0 initial_position = pos() while abs(pos()) > abs(initial_position) + 1 or side_count == 0: pixels = 250 if side_count == 0: angle = 0 else: angle = 162 turn_and_draw(angle, pixels) side_count += 1 end_fill()
And the call to this function is:
draw_complex_star(-150, -150, 'green', 'red')
Curious to see how our composition is so far?
Wait a little bit more, let’s draw the triangles first…
Drawing Isosceles Triangles with Python Turtle
To add isosceles triangles to our drawing we can use the function draw_generic_shape() that we have defined before.
Have a look at the logic to create the triangle in one of the previous sections if you don’t remember it.
Here is the new function we will define:
def draw_triangle(x, y, *colors): penup() goto(x, y) pendown() color(*colors) draw_generic_shape(120, 200, 3)
One difference compared to the previous example is that the previous triangle was equilateral (all three sides had the same length) while this time we want to draw isosceles triangles.
This means that we cannot use the draw_generic_shape() function, we have to define a separate function.
For this example, we will use isosceles triangles that have two 72 degrees base angles. This means the third angle is 36 degrees (the sum of the angles of a triangle is 180 degrees).
Here is our function:
def draw_triangle(x, y, *colors): penup() goto(x, y) pendown() color(*colors) begin_fill() side_count = 0 while side_count < 3: if side_count == 0: pixels = 125 angle = 0 elif side_count == 1: pixels = 200 angle = 108 else: pixels = 200 angle = 144 turn_and_draw(angle, pixels) side_count += 1 end_fill()
Remember that in isosceles triangles two sides have the same length (the ones drawn for side_count equal to 1 and 2 in the while loop).
Here is how we can call the function above to draw one triangle:
draw_triangle(-150, 150, 'yellow', 'green')
To call multiple triangles we will use a for loop and the range function:
def draw_triangles(x, y, *colors): for count in range(1, 5): setheading(0) draw_triangle(-200*count/2, 50*count/2, *colors)
We use the setheading() Turtle function to make sure the angle is set to zero before drawing every triangle (any initial angle different than zero would cause a rotation of the triangle).
Once again the values of x and y are passed to the draw_triangle() function and make sure the triangles don’t overlap with the other shapes drawn before.
Below you can see the calls to all the functions:
# Start drawing speed(10) draw_star(0, 150, 'green', 'blue') draw_circles(0, 0, 'blue', 'yellow') draw_complex_star(-150, -150, 'green', 'red') draw_triangles(-150, 150, 'yellow', 'green')
Notice that we are setting the speed to 10 considering that it can take a while to draw all the shapes.
…this is the masterpiece we have created together!
And this is just an example, you can create anything you want 🙂
We went through quite a lot in this Python tutorial:
- Starting from the basics of Turtle we have learned how to draw a square, a triangle, and a 5-point star using several Turtle functions like forward(), left(), and color().
- After that, we have seen how to use a more complex while logical expression to draw another interesting star shape. For that, we have used the absolute value of the position returned by the pos() function.
- Then we have drawn a circle, a semicircle, and a house. Every shape we have drawn has been filled with a color using the begin_fill() and end_fill() functions.
- We have also seen how to move around the x-y plane with the goto() function.
And do you remember which function we used to stop drawing lines while moving to a different position in the x-y plane?
Now it’s time for you to create whatever you want with Python Turtle.
Download the full source code for this tutorial to shortcut your learning process.
Claudio Sabato is an IT expert with over 15 years of professional experience in Python programming, Linux Systems Administration, Bash programming, and IT Systems Design.
With a Master’s degree in Computer Science, he has a strong foundation in Software Engineering and a passion for Robotics with projects that include Raspberry Pi and Arduino platforms.