Good luck in your learning, very nice start, i was much poorer in my begining! Viewing your code i suggest a structural change besides what @RootTwo and @dariosicily told.
The Spirit of Functions
Functions should be called with relevent paramenters. Currently when calling draw_triangle
we need to pass the a_turtle
parameter
draw_triangle(a_turtle, length)
but it would be nicer if we could call it by
draw_triangle(length)
directly.
Nicer Functions With Global Variables
By defining and using global variables, the above is achievable.
brent = turtle.Turtle()
window = turtle.Screen()
Then modifying functions using the global
keyword. The global
keyword allows you to use global variables within functions
def draw_polygon(length, sides):
global brent
for i in range(sides):
brent.forward(length)
brent.right(360 / sides)
The draw
function
def draw():
global brent, window
window.bgcolor("black")
brent.shape("turtle")
...
Then no need to each time add the a_turtle
parameter
The Class Approach
But, global variables might be a sign you need an OOP approach
This is an OOP approched by changing the above
class Sierpinski:
def __init__(self):
self.brent = turtle.Turtle()
self.window = turtle.Screen()
def draw_polygon(self, length, sides):
brent = self.brent
for i in range(sides):
brent.forward(length)
brent.right(360 / sides)
def draw_triangle(self, length):
self.draw_polygon(length, 3)
def draw_fractal_triangle(self, length, depth):
brent = self.brent
if (depth == 1):
self.draw_triangle(length)
else:
for i in range(1, 4):
self.draw_fractal_triangle(length/2, depth-1)
brent.forward(length)
brent.right(120)
def draw(self):
brent = self.brent
window = self.window
window.bgcolor("black")
brent.shape("turtle")
brent.color("yellow")
length = 200
brent.backward(length/2)
self.draw_fractal_triangle(length, 5)
window.exitonclick()
then to draw,
s = Sierpinski()
s.draw()
you could also implement
def draw_polygon(self, length, sides):
brent = self.brent
for i in range(sides):
brent.forward(length)
brent.right(360 / sides)
as
def draw_polygon(self, length, sides):
for i in range(sides):
self.brent.forward(length)
self.brent.right(360 / sides)
More control
Specifying the length and depth in the constructor might allow you to have more control, by changing values at one place, you modify it all
class Sierpinski:
def __init__(self):
self.brent = turtle.Turtle()
self.window = turtle.Screen()
self.length = 200
self.depth = 5
modifying in draw
def draw(self):
brent = self.brent
window = self.window
length = self.length
depth = self.depth
window.bgcolor("black")
brent.shape("turtle")
brent.color("yellow")
brent.backward(length/2)
self.draw_fractal_triangle(length, depth)
window.exitonclick()
Parameters
You can let users pass their own value by passing the values as parameters
class Sierpinski:
def __init__(self, length, depth):
self.brent = turtle.Turtle()
self.window = turtle.Screen()
self.length = length
self.depth = depth
usage:
s = Sierpinski(200, 5)
s.draw()
One last improvement could be adding parameters to draw
instead of the class itself.
Stack Overflow advice
When writing codes,
leave a line after the last ``` symbol to prevent this