Search code examples
pythonobjectinheritancepygamesubclassing

Python–Object AttributeError when accessing class attribute python


I have three classes: Item, Weapon, and BrassSword When I try to access one of BrassSword's attributes ex.(name,image,etc.) It says, AttributeError: class BrassSword has no attribute 'image'

Here's the code:

import pygame, math, random

class Item(object):
    def __init__(self,name,image,reuseable,value):
        self.image=pygame.image.load(image)
        self.itemattrs = ['name','image','reuseable','value']
        self.path = image
        self.name = name
        self.x=0
        self.y=0
        self.reusable = reuseable
        self.value = value
        self.rect = [self.x,self.y,self.image.get_size()[0],self.image.get_size()[1]]
    def onUse(self):
        pass
    def onThrow(self):
        pass

class Weapon(Item):
    def __init__(self,name,image,value,damage,maxdamage,speed):
        super(Weapon,self).__init__('Weapon',image,True,value)
        self.itemattrs = ['name','image','damage','maxdamage','value','speed']
        self.damage=damage
        self.maxdamage=maxdamage
        self.speed = speed # Cooldown in frames
        self.cooldown = 0
    def onUpdate(self):
        self.cooldown -= 1
    def onUse(self,targetEntity):
        if self.cooldown > 0:
            return
        self.cooldown = speed
        targetEntity.hp-=random.range(damage,maxdamage)

        if targetEntity.hp <= 0:
            targetEntity.onDie()
    def onThrow(self):
        pass # TODO: Add throwing weapons

class BrassSword(Weapon):
    def __init__(self):
        super(BrassSword,self).__init__('item.weapon.brass_sword','testlevel/Ball.png',True,value,3,10,12)

Solution

  • You didn't post the code that's actually causing the error - namely where you access the attribute. However, you can't access an instance attribute by referring to the class - they are stored in a separate __dict__. Your superclass sets these attributes when it is instantiated in __init__(), as a property of self. After this, they can only be accessed through that self instance.

    If you are trying to access the attribute similarly to this:

    a = BrassSword.image
    

    instead, you want to access it something like this:

    sword = BrassSword()
    a = sword.image
    

    or:

    sword = BrassSword().image
    

    If you want to have a single image shared across all BrassSword instances, you need to declare it a class attribute like this:

    class BrassSword(Weapon):
        image = 'path/to/image'
        def __init__(...):
            ...