PyDive PyDive - 7 months ago 16
Python Question

Questions about pulling object information from subclasses

my apologies if there are similar questions in regards to mine. I'm rather new to Python, and still getting used to OOP. That being said, if one of the many kind souls in this community could help in regards to my specific situation, or point me in the direction of similar questions that have been asked, -- though I'd like to note that Googling was no help and each question w/ similar errors were so widely different, and spanned so many different projects, I had a hard time grasping the solutions -- it would be greatly appreciated.

Let's say I have a file named 'objects.py' to store most of my class objects for a text based game I'm developing, and in that file I have a class named 'Occupation'. Class 'Occupation' holds variables that are used as modifiers for the 'Player' class that will be described a little more later on.

The idea is that in the root file, namely 'root.py', the player will be able to choose from a list of player occupations, e.g. 'wizard' or 'knight', and have the information from the respective Occupation classes replace the current Player variable information.

'player.py' file:

import objects

class Player(object):
nextlevel = 30
# 'nextlevel' is the gold required for a level up.
def __init__(self):
self.name = ''
self.level = 1
self.health = 1
self.stamina = 0
self.mana = 0
self.skills = {'str': 0, 'def': 0, 'dex': 0, 'int': 0, 'chr': 0, 'lck': 0}
self.spells = []
self.inventory = [{'armor': [objects.PrisonerRobes()], 'weapons': [objects.IronDagger()], 'bows': [], 'potions': [], 'misc': []}, objects.Gold(0), objects.Arrow(0)]
self.victory = False


'objects.py' file:

class Occupation(object):
# Base class for all occupations / classes, e.g. 'knight' or 'wizard'.
classlist = ['warrior', 'knight', 'paladin', 'druid', 'warlock', 'wizard']
def __init__(self, name, hp, sp, mp, strv, defv, dexv, intv, chrv, lckv):
# The variable names of 'strv', 'defv', etc. stand for 'strength value', 'defence value', etc.
self.name = name
self.health = health
self.stamina = stamina
self.mana = mana
self.strv = strv #skill values
self.defv = defv
self.dexv = dexv
self.intv = intv
self.chrv = chrv
self.lckv = lckv

def __str__(self):
details = '{0}: HP: {1}, SP: {2}, MP: {3} // [STR: {4}, DEF: {5}, DEX: {6}, INT: {7}, CHR: {8}, LCK: {9}]'
return details.format(self.name, self.health, self.stamina, self.mana, self.strv, self.defv, self.dexv, self.intv, self.chrv, self.lckv)

class Warrior(Occupation):
def __init__(self):
super(Warrior, self).__init__('Warrior', 75, 50, 25, 12, 8, 12, 5, 8, 5)


'root.py' file:

from player import Player
import objects

def new_game():
while True:
print 'Only one class, and it is Warrior!'
print objects.Warrior()
classchoice = raw_input('Please type the full name of the class you wish to select.: ').lower()
playerclass = classchoice.title()
if classchoice != '':
characterclass = getattr(objects, playerclass)
player.health = characterclass.health
player.stamina = characterclass.stamina
player.mana = characterclass.mana
player.skills['str'] = characterclass.strv
player.skills['def'] = characterclass.defv
player.skills['dex'] = characterclass.dexv
player.skills['int'] = characterclass.intv
player.skills['chr'] = characterclass.chrv
player.skills['lck'] = characterclass.lckv
print 'You have chosen {0} as your class.'.format(characterclass.name)
confirm = raw_input('Is this correct? Type [Y] or [N] for yes/no respectively.: ').lower()
if confirm == 'y':
break
elif confirm == 'n':
continue
else:
print 'Not a valid keystroke!'
continue


The problem appears when typing 'warrior' when choosing a player class.:

line 48[in my original file]: player.health = characterclass.health
AttributeError: type object 'Warrior' has no attribute 'health'


It seems that I can't reference the variables that I want to, when trying to update pre-existing Player values. The 'Warrior' class, as far as I can tell, has the variable 'health', but I can't seem to access it. Am I misunderstanding how classes and subclasses work in Python? Or is it something else?

Thanks for any help.

Answer

characterclass = getattr(objects, playerclass) getattr() returns the value of named attribute of an object other than the object itself. characterclass is not an instance of Warrior, therefore you cannot refer to attribute health

getattr(object, name[, default]) Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s attributes, the result is the value of that attribute. For example, getattr(x, 'foobar') is equivalent to x.foobar. If the named attribute does not exist, default is returned if provided, otherwise AttributeError is raised.

You need to create warrior instance as:

warrior = objects.Warrior()
warrior.health