Skip to content

Week 4 - Functions and Interfaces

Functions and Interfaces

The jupyturtle OR turtle module

  • jupyturtle: Used for turtle graphics to create simple drawings in Google CoLab.
  • Main functions:
  • make_turtle(): Creates a canvas and a turtle to draw.
  • forward(100): Moves the turtle 100 units forward.
  • left(90), right(90): Turns the turtle by a specified angle in degrees.
  • turtle: Is turtle graphics to create simple drawings in IDEs like PyCharm.
  • t = turtle.Turtle(): Creates a window canvas and a turtle to draw.
  • t.forward(100): Moves the turtle 100 units forward.
  • t.left(90), right(90): Turns the turtle by a specified angle in degrees.

Google CoLab Code Example:

1
2
3
4
5
6
from jupyturtle import make_turtle, forward, left

make_turtle()
forward(100)
left(90)
forward(100)

PyCharm Code Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import turtle

# Create a turtle object
t = turtle.Turtle()

# Hide the turtle and set speed
t.speed(10)  # 1 is slow, 10 is fast, 0 is instant
t.hideturtle()

# Create a window to draw in
# Create a new turtle screen and set its background color
screen = turtle.Screen()
screen.bgcolor("darkblue")
# Set the width and height of the screen
screen.setup(width=600, height=600)
# Clear the screen
t.clear()

t.forward(100)
t.left(90)
t.forward(100)

# Close the turtle graphics window when clicked
turtle.exitonclick()

Repeating Commands

  • Use for and while loops to simplify repetitious code:
    1
    2
    3
    4
    5
    6
    from jupyturtle import make_turtle, forward, left
    
    make_turtle()
    for i in range(4):
        forward(50)
        left(90)
    

Encapsulation and Generalization

  • Encapsulation: Wrap code into a function for reuse.
  • Generalization: Make functions more flexible by using parameters.
1
2
3
4
5
6
7
8
def square(length):  # Parameters are used to make the code more general.
    for i in range(4):
        forward(length)
        left(90)

make_turtle()
square(30)  # Then we can modify behavior by passing different arguments.
square(60)

Refactoring

  • Refactoring: Improve code structure by organizing repeated logic into reusable functions (e.g., polyline).
  • Creating arcs: The arc function draws part of a circle based on an angle.
    • Both of the functions below were used to demonstrate how the author refactored functions like polygon and circle into simpler more generalized implementaions.
    • Refactoring is the process, generalization is what occurred.
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      def polyline(n, length, angle):
          for i in range(n):
              forward(length)
              left(angle)
      
      def arc(radius, angle):
          arc_length = 2 * math.pi * radius * angle / 360
          n = 30
          length = arc_length / n
          step_angle = angle / n
          polyline(n, length, step_angle)
      
      make_turtle(delay=0)
      arc(radius=70, angle=70)
      

Stack Diagrams (Yes Again)

  • Let’s use Python Tutor to visualize the stack of function calls when calling circle -> arc -> polyline:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    def polyline(n, length, angle):  # This is really generalized and flexible now.
        for i in range(n):
            my_turtle.forward(length)
            my_turtle.left(angle)
    
    def arc(radius, angle):  # Similar to circle, but can do fractional circles.
        arc_length = 2 * math.pi * radius * angle / 360  # Here we calculate how much of the arc of a circle to draw.
        n = 30  # We fix the segments to 30 still, but this is 30 segments per arc, so smaller arcs will appear smoother.
        length = arc_length / n
        step_angle = angle / n  # Since we are covering a fraction of the arc of a circle, we need smaller angles too.
        polyline(n, length, step_angle)  # And now we approximate the arc with polyline.
    
    def circle(radius):
        arc(radius, 360)
    

Plan Your Development

  • You can take steps to make your development process more efficient and less error prone. Here are some suggestions:
    1. Start small without functions.
    2. Encapsulate parts of code into functions.
    3. Generalize functions with parameters.
      • The process of doing this is often referred to as Interface design and the function headers are often called interfaces.
    4. Refactor as needed for cleaner, reusable code.
  • Rinse and Repeat!

Docstrings

  • Docstrings: Document function interfaces, parameter types, and effects.
  • Multiline strings: Use triple quotes for detailed docstrings.
  • Example of a good docstring:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    def polyline(n, length, angle):
        """Draws line segments with the given length and angle between them.
    
        n: integer number of line segments
        length: length of the line segments
        angle: angle between segments (in degrees)
        """
        for i in range(n):
            forward(length)
            left(angle)
    
  • Later we will see that you can use docstrings to help automatically test your code!

Debugging

  • Preconditions: Conditions that must be true before the function is called.
  • Postconditions: Conditions that should be true after the function has executed.
  • Responsibility: If preconditions aren’t met, it’s the caller’s fault. If postconditions aren’t met, it’s the function’s fault.