I'm supposed to call on 2 different classes that then run the program so that the menu appears and the user chooses an option. I have most of the program running, but cannot check if anything is working because I keep getting the error that animal_type and name are not defined and am having trouble figuring out why. I've attached parts of each program.
Main file:
import Animal
import Zoo
def main():
#set user choice
animal = Animal.Animal()
Zoo.py:
import Animal
class Zoo:
#initialize attribute
def __init__(Animal):
Animal.__animals = []
def add_animal(Animal, animals):
Animal.__animals.append(animal)
def show_animals(Animal):
size = len(animals)
if size == 0:
print("There are no animals in your zoo!")
else:
return __animals
Animal.py:
import random
class Animal:
#initialize attributes
def __init__(self,animal_type, name, mood = None):
self.__animal_type = animal_type
self.__name = name
if mood:
self.__mood = mood
else:
self.check_mood()
# set methods
def set_animal_type(self, animal_type):
self.__animal_type = animal_type
def set_name(self, name):
self.__name = name
def set_mood(self, mood):
self.__mood = mood
In your main function, you aren't passing any of the required variables to Animal. (animal_type and animal)
You need to define them or just directly call with them.
animal = Animal.Animal('Goat', 'Billy')
or
atype = 'Goat'
aname = 'Billy'
animal = Animal.Animal(atype, aname)
Related
I am currently developing a short text-based adventure so I can learn how to use Classes within Python. As part of this, I am trying to create a combat system where the player could choose an NPC to attack.
The aim is that the player can enter the name of the NPC and the weapon they want to use. A method in the target's class will then be called, to lose health based on the damage of the weapon.
My current code is below:
class npc:
def __init__(self, name, alliance):
self.name = name
self.alliance = alliance
def loseHealth(self, health, dmg):
self.dmg = dmg
self.health = self.health - dmg
def usePotion(self, health, pType):
if pType == "great":
self.health = min(self.health + 50,self.maxHealth)
elif pType == "normal":
self.health = min(self.health + 25,self.maxHealth)
else:
pass
def attack(self, target, weaponDmg):
if target in npcList:
target.loseHealth(self.health, weaponDmg)
class human(npc):
maxHealth = 100
health = 100
def __init__(self, name, alliance):
super().__init__(name, alliance)
class orc(npc):
maxHealth = 200
health = 200
def __init(self, name, alliance):
super().__init__(name, alliance)
weaponDmg = {'sword':10,'axe':20}
alice = human("alice","good")
bob = orc("bob","evil")
npcList = [alice, bob]
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
alice.attack(target,weaponDmg[weapon]) #using alice temporarily until I have a person class sorted
print(target.health)
The simple and pythonic answer is to use a dict of NPCs keyed by name, the same way you’re already doing it with weapons:
npcs = {‘alice’: alice, ‘bob’: bob}
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
alice.attack(npcs[target], weaponDmg[weapon])
print(target.health)
And if you want to look up the attacking NPC by user-supplied name as well as the attackee, you can do the same thing there:
npcs[attacker].attack(npcs[target], weaponDmg[weapon])
If you really want to do this inside the attack method you can keep passing in target as a name (string) and do this:
if target in npcs:
npcs[target].loseHealth(self.health, weaponDmg)
... but that probably isn’t a very good design. It means you’re sharing a global variable, and your NPC objects all “know” about that global dict and all the NPCs in it, which doesn’t seem like part of their responsibility.
You can make this a little less repetitive by creating the dict with a comprehension:
npcs = {npc.name: npc for npc in (alice, bob)}
... or by just creating them directly in the dict instead of in variables that you’re probably never going to otherwise use:
npcs = {}
npcs[‘alice’] = human("alice","good")
npcs[‘bob’] = orc("bob","evil")
You can call a method on an instance by using getattr, here is an example:
>>> class Test:
... def my_method(self, arg1, arg2):
... print(arg1, arg2)
...
>>> t = Test()
>>> getattr(t, 'my_method')('foo', 'bar')
foo bar
class player(object):
def __init__(self):
self.health = 100
self.stats = {'STR': 0,
'DEF':0}
class create_character(object):
def choose_class(self):
inp = input("Please choose a class!: ").lower()
s = ("Knight, Archer, or Mage")
print(s)
if inp == 'knight':
self.stats['STR'] = 15
self.stats['DEF'] = 15
print(self.stats)
The problem I'm facing currently, is that when I reference self.stats under create_character, it tells me that specific class doesn't have a 'self.stats'. If I try player.self.stats or player.stats, it tells me the same thing, that the class doesn't have those attributes. How can I reference a dictionary or a variable from another class, and change its properties. Also, when I print self.health, or self.stats, or self.name or whatever properties the player class hold, it gives me a bunch of unneeded information. Is there a way to exclude the extra information?
I believe that this will do the job that you are looking for:
class player(object):
def __init__(self):
self.health = 100
self.stats = {'STR': 0,
'DEF':0}
def choose_class():
inp = input("Please choose a class (Knight, Archer, or Mage): ").lower()
if inp == 'knight':
# create the player object
p = player()
# changes the values for the attributes in the player object
p.stats['STR'] = 15
p.stats['DEF'] = 15
print(p.stats)
# calls the function to choose the class
choose_class()
This is not really a good coding style though, so I would recommend following an OOP Python tutorial.
I am trying to make a class called Zoo.py. I have made another class program called Animal.py which displays the information that needs to be printed on another program called Zookeeper. I have no problem with the Zookeeper program.
My problem is that I do not know how to make the Zoo class program that has an attribute called __animals which will be a list used to store Animal objects. Then I will use the __init__ method to create an empty list for __animals.
I will create an add_animal method that will receive an Animal object and append it to the __animals list.
Then I will make a show_animals method that will print information about each of the Animal objects within __animals and, if no Animals have been added to the list, it should print out a message saying that there are no Animals.
Here is my Animals.py program that the Zoo program needs to get information from:
# This program defines the Animal class
import random
class Animal:
# Define what happens when a new animal object is created
def __init__(self, animal_type, animal_name):
self.__animal_type = animal_type
self.__name = animal_name
self.__mood = "happy"
# Return the animal's type
def get_animal_type(self):
return self.__animal_type
# Return the animal's name
def get_name(self):
return self.__name
# Determine and return the animal's mood
def check_mood(self):
# Pick a number between 1 and 3
random_number = random.randint(1, 3)
# Set the animal's mood based on the random number
if random_number == 1:
self.__mood = "happy"
elif random_number == 2:
self.__mood = "hungry"
elif random_number == 3:
self.__mood = "sleepy"
# Finally, return the mood
return self.__mood
For the Zoo class program so far this is all I have:
import Animals
class Zoo:
__animals = []
# Use method to create an empty list for __animals
def __init__(self):
self.__animals = animal_list
# Receive an Animal object and append it to the __animals list
def add_animal(self):
animal.append(animal_list)
# Determine and return the animal's mood
def show_animals(self):
return animal_list
I do not need any help for the ZooKeeper.py but here is what the program will look like once Zoo.py works:
Zoo Options
-----------
1. Add Animal
2. Show Animals
3. Exit
What would you like to do? 1
What type of animal would you like to create? Platypus
What is the animal's name? Penelope
Zoo Options
-----------
1. Add Animal
2. Show Animals
3. Exit
What would you like to do? 2
Animal List
-----------
Penelope the Platypus is sleepy
First off, if you want to add an animal object to the zoo, you need to pass the object as a parameter to the add_animal method.
As an example:
class Zoo:
def add_animal(self, animal):
self.__animals.append(animal)
I keep getting an error of
NameError: name animal_type is not defined
or
TypeError: __init__() missing 2 required positional arguments: 'animal_type' and 'name'
no matter if I change the line to
animal = Animal.Animal(animal_type, animal)
or
animal = Animal.Animal()
and it has this later:
#Add animal to list
def addAnimal(animal):
atype = input("What type of animal would you like to create? ")
theAnimal = atype
theAnimal = Animal.Animal()
theAnimal.set_animal_type(atype)
aname = input("What is the animal's name? ")
theName = aname
theName = Animal.Animal()
theName.set_name(aname)
zookeeper.add_animal(theAnimal, theName)
To give some background, this program has 2 classes that it imports.
Here is one that I am calling:
import random
class Animal:
#initialize attributes
def __init__(self,animal_type, name, mood = None):
self.__animal_type = animal_type
self.__name = name
if mood:
self.__mood = mood
else:
self.check_mood()
# set methods
def set_animal_type(self, animal_type):
self.__animal_type = animal_type
def set_name(self, name):
self.__name = name
You are getting the NameError because in your second file (the one you are importing the Animal class into), you haven't defined your variables.
animal = Animal.Animal(animal_type, animal)
animal_type and/or animal have not been defined.
As for the TypeError, the problem with
animal = Animal.Animal()
is that you aren't passing any of the required variables. animal_type and animal.
For example:
import Animal # Animal.py
atype = 'Snake'
name = 'George'
a = Animal.Animal(atype, name)
Or simply
import Animal # Animal.py
a = Animal.Animal('Snake', 'George')
Other Problems (after the edit):
1.)
You don't need to create a new class instance when you set_name or set_animal_type. (in addAnimal)
What you should be doing is this:
theAnimal = Animal.Animal(atype, aname)
2.)
You need to have your inputs first. Like so:
def addAnimal(animal):
atype = input("What type of animal would you like to create? ")
aname = input("What is the animal's name? ")
theAnimal = Animal.Animal(atype, aname)
theAnimal.set_animal_type(atype)
theAnimal.set_name(aname)
zookeeper.add_animal(theAnimal, aname)
3.)
Your addAnimal function does not need any variables. They are not used.
def addAnimal(animal):
should be
def addAnimal():
I am on exercise 43 doing some self-directed work in Learn Python The Hard Way. And I have designed the framework of a game spread out over two python files. The point of the exercise is that each "room" in the game has a different class. I have tried a number of things, but I cannot figure out how to use the returned value from their initial choice to advance the user to the proper "room", which is contained within a class. Any hints or help would be greatly appreciated.
Apologies for the poor code, I'm just starting out in python, but at my wit's end on this.
Here is the ex43_engine.py code which I run to start the game.
from ex43_map import *
import ex43_map
import inspect
#Not sure if this part is neccessary, generated list of all the classes (rooms) I imported from ex43_map.py, as I thought they might be needed to form a "map"
class_list = []
for name, obj in inspect.getmembers(ex43_map):
if inspect.isclass(obj):
class_list.append(name)
class Engine(object):
def __init__(self, room):
self.room = room
def play(self):
# starts the process, this might need to go inside the loop below
next = self.room
start.transportation_choice()
while True:
print "\n-------------"
# I have tried numerous things here to make it work...nothing has
start = StartRoom()
car = CarRoom()
bus = BusRoom()
train = TrainRoom()
airplane = AirplaneRoom()
terminal = TerminalRoom()
a_game = Engine("transportation_choice")
a_game.play()
And here is the ex43_map.py code
from sys import exit
from random import randint
class StartRoom(object):
def __init__(self):
pass
def transportation_choice(self):
print "\nIt's 6 pm and you have just found out that you need to get to Chicago by tomorrow morning for a meeting"
print "How will you choose to get there?\n"
print "Choices: car, bus, train, airplane"
choice = raw_input("> ")
if choice == "car":
return 'CarRoom'
elif choice == "bus":
return 'BusRoom'
elif choice == "train":
return 'TrainRoom'
elif choice == "airplane":
return 'AirplaneRoom'
else:
print "Sorry but '%s' wasn't a choice." % choice
return 'StartRoom'
class CarRoom(object):
def __init__(self):
print "Welcome to the CarRoom"
class BusRoom(object):
def __init__(self):
print "Welcome to the BusRoom"
class TrainRoom(object):
def __init__(self):
print "Welcome to the TrainRoom"
class AirplaneRoom(object):
def __init__(self):
print "Welcome to the AirplaneRoom"
class TerminalRoom(object):
def __init__(self):
self.quips = [
"Oh so sorry you died, you are pretty bad at this.",
"Too bad, you're dead buddy.",
"The end is here.",
"No more playing for you, you're dead."
]
def death(self):
print self.quips[randint(0, len(self.quips)-1)] # randomly selects one of the quips from 0 to # of items in the list and prints it
exit(1)
Instead of returning a string try returning an object, ie
if choice == "car":
return CarRoom()
It might be a good idea to make a Room class, and derive your other rooms from it.
The Room base class can then have a class variable which automatically keeps track of all instantiated rooms.
I haven't thoroughly tested the following, but hopefully it will give you some ideas:
# getters.py
try:
getStr = raw_input # Python 2.x
except NameError:
getStr = input # Python 3.x
getStr.type = str
def typeGetter(dataType):
def getter(msg):
while True:
try:
return dataType(getStr(msg))
except ValueError:
pass
getter.type = dataType
return getter
getInt = typeGetter(int)
getFloat = typeGetter(float)
getBool = typeGetter(bool)
def getOneOf(*args, **kwargs):
"""Get input until it matches an item in args, then return the item
#param *args: items to match against
#param getter: function, input-getter of desired type (defaults to getStr)
#param prompt: string, input prompt (defaults to '> ')
Type of items should match type of getter
"""
argSet = set(args)
getter = kwargs.get('getter', getStr)
prompt = kwargs.get('prompt', '> ')
print('[{0}]'.format(', '.join(args)))
while True:
res = getter(prompt)
if res in argset:
return res
.
# ex43_rooms.py
import textwrap
import random
import getters
class Room(object):
# list of instantiated rooms by name
ROOMS = {}
#classmethod
def getroom(cls, name):
"""Return room instance
If named room does not exist, throws KeyError
"""
return cls.ROOMS[name]
def __init__(self, name):
super(Room,self).__init__()
self.name = name
Room.ROOMS[name] = self
def run(self):
"""Enter the room - what happens?
Abstract base method (subclasses must override)
#retval Room instance to continue or None to quit
"""
raise NotImplementedError()
def __str__(self):
return self.name
def __repr__(self):
return '{0}({1})'.format(self.__class__.__name__, self.name)
class StartRoom(Room):
def __init__(self, name):
super(StartRoom,self).__init__(name)
def run(self):
print textwrap.dedent("""
It's 6 pm and you have just found out that you need to get to Chicago
by tomorrow morning for a meeting! How will you get there?
""")
inp = getters.getOneOf('car','bus','train','airplane')
return Room.getroom(inp)
class CarRoom(Room):
def __init__(self,name):
super(CarRoom,self).__init__(name)
class BusRoom(Room):
def __init__(self,name):
super(BusRoom,self).__init__(name)
class TrainRoom(Room):
def __init__(self,name):
super(TrainRoom,self).__init__(name)
class PlaneRoom(Room):
def __init__(self,name):
super(PlaneRoom,self).__init__(name)
class TerminalRoom(Room):
def __init__(self,name):
super(TerminalRoom,self).__init__(name)
def run(self):
print(random.choice((
"Oh so sorry you died, you are pretty bad at this.",
"Too bad, you're dead buddy.",
"The end is here.",
"No more playing for you, you're dead."
)))
return None
# create rooms (which registers them with Room)
StartRoom('start')
CarRoom('car')
BusRoom('bus')
TrainRoom('train')
PlaneRoom('airplane')
TerminalRoom('terminal')
.
# ex43.py
from ex43_rooms import Room
def main():
here = Room.getroom('start')
while here:
here = here.run()
if __name__=="__main__":
main()