Hello python gurus! I dabble in python casually, and I've just recently begun to use classes. For the most part they've proven very helpful, but this error has me stumped:

creature.health=creature.health-2*creature.metabolsim/resolution
AttributeError: predator instance has no attribute 'metabolsim'

Here's the full code of the program (it's designed to run a very simplistic simulation of evolution in an ecosystem), still riddled with errors, most likely.
The blocks pertinent to this issue are:
line 125 where the function is called,
the function itself starting on line 101,
and the definition of the class Predator, beginning line 62.

(I know it runs a little long, I'll clean it up with more functions once I get it running as is):

import random
import math

### DEFINING CLASSES ###

#starting plants will be generated from prototypes
class Protoplant:
    def __init__(self):
        self.Coord=[random.randrange(0,100),random.randrange(0,100)]
        self.health=random.randrange(50,100)
        self.split=random.randrange(150,200)
        self.plasticity=random.randrange(0,20)

class Protoprey:
    def __init__(self):
        self.Coord=[random.randrange(0,100),random.randrange(0,100)]
        self.health=random.randrange(400,500)
        self.split=self.health*2
        self.metabolism=random.randrange(2,5)
        self.paranoia=random.gauss(1.0,0.5)
        self.plasticity=random.randrange(0,20)
    
class Protopredator:
    def __init__(self):
        self.Coord=[random.randrange(0,100),random.randrange(0,100)]
        self.health=random.randrange(800,1000)
        self.split=self.health*2
        self.metabolism=random.randrange(3,6)
        self.plasticity=random.randrange(0,20)

def MAKE_ATTRIBUTES(child,parent,Attributes,Morph):
    child.Coord=[parent.Coord(0)+random.gauss(0,5),parent.coord(1)+random.gauss(0,5)]
    child.plasticity=parent.plasticity+random.randrange(-5,5)
    for attribute in Attributes:
        child.attribute=parent.attribute+random.gauss(0,Morph[Attributes.index(attribute)])*parent.plasticity

class Plant:
    def __init__(self, parent):
#        MAKE_ATTRIBUTES(self,parent,['health','split'],[1,1])
        self.Coord=[parent.Coord[0]+random.gauss(0,5),parent.Coord[1]+random.gauss(0,5)]
        self.health=parent.health+random.gauss(0,parent.plasticity)
        self.split=parent.split+random.gauss(0,parent.plasticity)
        self.plasticity=parent.plasticity+random.randrange(-5,5)
    def DEATH(self):
        if random.randrange(0,int(self.health*resolution)*10)==0:
            Plants.remove(self)

class Prey:
    def __init__(self,parent):
        self.Coord=[parent.Coord[0]+random.gauss(0,5),parent.Coord[1]+random.gauss(0,5)]
        self.health=parent.health+random.gauss(0,parent.plasticity)
        self.split=parent.split+random.gauss(0,parent.plasticity)
        self.metabolism=parent.metabolism+random.gauss(0,0.05*parent.plasticity)
        self.paranoia=parent.paranoia+random.gauss(0,0.05*parent.plasticity)
        self.plasticity=parent.plasticity+random.randrange(-5,5)
    def ACT(self):
        if SEEK(self,Plants,2)<SEEK(self,Predators,2)*self.paranoia:
            CHASE(self,SEEK(self,Plants,1),Plants)
        else:
            FLEE(self,SEEK(self,Predators,1))
                  
class Predator:
    def __init__(self,parent):
        self.Coord=[parent.Coord[0]+random.gauss(0,5),parent.Coord[1]+random.gauss(0,5)]
        self.health=parent.health+random.gauss(0,parent.plasticity)
        self.split=parent.split+random.gauss(0,parent.plasticity)
        self.metabolism=parent.metabolism+random.gauss(0,0.05*parent.plasticity)
        self.plasticity=parent.plasticity+random.randrange(-5,5)        

### DEFINING FUNCTIONS ###

def CHASE(mover,point,Point_Family): #moves an object (mover) towards another object (point)
    mag=math.sqrt((point.Coord[0]-mover.Coord[0])**2+(point.Coord[1]-mover.Coord[1])**2)#calculates the distance between the objects
    if mag < 3*(mover.metabolism/resolution): # If the mover is very close to the predator
        mover.health=mover.health+point.health #cause mover to absorb point's health
        Point_Family.remove(point) #then remove the point        
    else:
        for c in range (0,2):
            mover.Coord[c]=mover.Coord[c]+(point.Coord[c]-mover.Coord[c])*mover.metabolism/(mag*resolution) #moves mover towards point

def FLEE(mover,point): #moves an object (mover) away from another object (point)
        mag=math.sqrt((point.Coord[0]-mover.Coord[0])**2+(point.Coord[1]-mover.Coord[1])**2)#calculates the distance between the objects
        for c in range (0,2):
            mover.Coord[c]=mover.Coord[c]-(point.Coord[c]-mover.Coord[c])*mover.metabolism/(mag*resolution) #moves mover away from point

def SEEK(mover,Point_Family,output):
    Magnitudes=[]#A list of the distances from each point to the mover
    for point in Point_Family:
        Magnitudes.append(math.sqrt((point.Coord[0]-mover.Coord[0])**2+(point.Coord[1]-mover.Coord[1])**2))#calculates the distance to a point
    if output==1:
        return(Point_Family[Magnitudes.index(min(Magnitudes))])#returns the point that corresponds to the least value in Magnitudes
    else:
        return(min(Magnitudes))

def SPLIT(splitter,Family,Class):
    if splitter.health > splitter.split:
        print('a', splitter ,'is born!' )
        splitter.health=int(splitter.health/2)
        Family.append(Class(splitter))

def DEPLETE (creature):
    creature.health=creature.health-2*creature.metabolsim/resolution

###INTRODUCING OBJECTS###
cycles=1000.0
resolution=100        

Plants=[]
Preys=[]
Predators=[]
#creating sets of creatures#

for x in range(0,100):
    Plants.append(Plant(Protoplant()))
for x in range (0,20):
    Preys.append(Prey(Protoprey()))
for x in range (0,5):
    Predators.append(Predator(Protopredator()))
    
###EXECUTE PROGRAM###

while cycles > 0:
    for pred in Predators:
        CHASE(pred,SEEK(pred,Preys,1),Preys)
        DEPLETE (pred)
        SPLIT(pred,Predators,Predator)
    for pre in Preys:
        pre.ACT()
        DEPLETE(pre)
        SPLIT(pre,Preys,Prey)
        pre.Coord[0]=pre.Coord[0]%100
        pre.Coord[1]=pre.Coord[1]%100
    for plan in Plants:
        plan.health=plan.health+10.0/resolution
        plan.DEATH()
        SPLIT(plan,Plants,Plant)
        plan.Coord[0]=plan.Coord[0]%100
        plan.Coord[1]=plan.Coord[1]%100
    print(cycles)
    print('plants:', len(Plants))
    print('prey:', len(Preys))
    print('predators:', len(Predators))
    cycles=cycles-1.0/resolution

What has me stumped here is that in the line just before 128, the CHASE function calls the metabolism attribute as well, and does so without a hitch.

I became even more confused after running the debugger: in debug mode (in the eclipse platform), I enter the DECAY function, metabolism is right there in the list of the class instance's attributes, and the debugger seems to execute line 102 without a hitch, returning to the deplete function. I hit "step into" two more times after this, and the program crashes with the error:

Traceback (most recent call last):
  File "C:\Users\John Smith\Documents\workspace\stand-alone scripts\src\Evo_classes.py", line 133, in <module>
    DEPLETE (pred)
  File "C:\Users\John Smith\Documents\workspace\stand-alone scripts\src\Evo_classes.py", line 107, in DEPLETE
    creature.health=creature.health-2*creature.metabolsim/resolution
AttributeError: Predator instance has no attribute 'metabolsim'

sorry about the long post, but I wasn't sure which pieces of information would be relevant. Thank you for your time and assistance.

creature.metabolism
creature.metabolsim

commented: spot on -3
commented: upvoted for Griboullis (was downvote error) +15

creature.metabolism
creature.metabolsim

Sorry lrh9, I wanted to upvote your post and I downvoted it by mistake. Perhaps a moderator can change my vote, thanks :(

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.