Search code examples
pythonoopattributeerrorpython-turtle

How to fix the 'AttributeError' when working with classes and turtle?


I am trying to make a natural selection simulator using turtle, which I am fairly familiar with, and OOP, which is as good as completely new to me. I can't seem to find an answer to my specific problem, which could be because I just do not understand it. My code currently looks like this:

import turtle
import time
import random

turtle.speed(50)
turtle.setworldcoordinates(-50, -50, 1920, 1080)

class Creature: # This class contains the blueprint for the 'blob' creature.
    def __init__(self, speed, location_x, location_y):  # Initializes parameters.
        self.speed = speed                              # Speed of the blob.
        self.location_x = location_x                    # X coordinate of the blob, paired with y forms location.
        self.location_y = location_y                    # Y coordinate of the blob, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    def spawn(self):
        turtle.penup()
        turtle.goto(Creature.location_x, Creature.location_y)   # Lets the turtle spawn in a random point.
        turtle.color("Blue")
        turtle.dot(20)
    def move(self):
        pass

class Apple: # This class contains the blueprint for the food (apples) that the blobs can eat.
    def __init__(self, location_x, location_y):
        self.location_x = location_x
        self.location_y = location_y
    def spawn(self):
        turtle.penup()
        turtle.goto(Apple.location_x, Apple.location_y)
        turtle.color("Red")
        turtle.dot(20)
    
blob1 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob2 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob3 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob4 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob5 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob6 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob7 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob8 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob9 =  Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))
blob10 = Creature(1.5, random.randint(0, 1000), random.randint(0, 1000))

apple1 = Apple(random.randint(0, 1000), random.randint(0, 1000))
apple2 = Apple(random.randint(0, 1000), random.randint(0, 1000))
apple3 = Apple(random.randint(0, 1000), random.randint(0, 1000))
apple4 = Apple(random.randint(0, 1000), random.randint(0, 1000))
apple5 = Apple(random.randint(0, 1000), random.randint(0, 1000))

Creature.spawn(all)

Apple.spawn(all)

turtle.exitonclick()

I have tried to change some things around, but nothing helped. A explanation would also be very helpful, as well as some advice on how to prevent myself from having this problem in the future. Also, I don't know if it is possible, but can you let your program make an instance of a class? The errorcode I got was the following:

Traceback (most recent call last):
  File "c:\Users\sidne\Programs(Python)\Natural selection simulator.py", line 64, in <module>
    blob1.spawn()
  File "c:\Users\sidne\Programs(Python)\Natural selection simulator.py", line 15, in spawn
    turtle.goto(Creature.location_x, Creature.location_y)   # Lets the turtle spawn in a random point.
                ^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Creature' has no attribute 'location_x'

Solution

  • You have a few errors, but you weren't far off from a working code.

    First off, in the spawn() functions, you need to change Creature.location_x and Apple.location_x to self.location_x. Do the same for .location_y.


    Your next issue is you're calling Creature.spawn() and Apple.spawn(). This is calling the class itself, but we want to call the methods for instances of the class.

    blobs = [Creature(1.5, random.randint(0, 1000), random.randint(0, 1000)) for _ in range(10)]
    apples = [Apple(random.randint(0, 1000), random.randint(0, 1000)) for _ in range(5)]
    

    I went ahead and made your Creatures and Apples into their own lists, since this is much easier to handle. This essentially does the same thing as your fifteen lines of code, but in only two lines.

    Finally, we loop through each list and call the .spawn() method of each instance.

    for blob in blobs:
        blob.spawn()
    
    for apple in apples:
        apple.spawn()
    

    Final result?

    final result

    Hope this helped!