class Character:
def __init__(self, name,):
self.name = name
def help (self):
print (menu.keys())
def name(self):
print ("Hast du schon vergessen ? ")
c = Character
c.name = input("Wie heißt du denn ? ")
print ("Help, wenn du Hilfe brauchst")
menu ={"help":Character.help,
"name":Character.name}
#This function allows you call up the main menu at any point in the game.
while True :
line = input(">")
args = line.split()
if len(args) < 4:
Befehl_vorhanden = False
for c in menu.keys():
if args[0] == c[:len(args[0])]:
menu[c](c)
Befehl_vorhanden = True
break
if not Befehl_vorhanden:
print ("ich verstehe dich nicht.")
Thanks to the help of the other stack overflow users, I was able to get my code running. I have created a menu for my game that can be called up at any point. However, it won't allow me to print any text. If I input "name" for example, it gives me.
TypeError: 'str' object is not callable
I have even tried using it as a basic function without my menu. However, I can't seem to get this code to work.
Any suggestions would be greatly appreciated.
Thanks in advance,
Chris
Your line:
c.name = input("Wie heißt du denn ? ")
assigns the method Character.name to a string, hence you get 'str' object not callable on the line menu[c](c) because menu[c] is Character.name.
Update:
This program may be closer to the one you are looking for:
class Character:
def __init__(self, name):
self.namen = name
def help (self):
print (menu.keys())
def name(self):
print ("Hast du schon vergessen ? ", self.namen)
c = Character(input("Wie heißt du denn ? "))
print ("Help, wenn du Hilfe brauchst")
menu ={"help":c.help,
"name":c.name}
#This function allows you call up the main menu at any point in the game.
while True :
line = input(">")
args = line.split()
if len(args) < 4:
if args[0] in menu:
k = args[0]
menu[k]()
else:
print ("ich verstehe dich nicht.")
Note how I changed __init__() to perform: self.namen = name since your version also overwrites the declaration of def name(self):.
Related
So, I'm working on a command line RPG for the sake of filling time, and re-stretching my Python muscles as I've been out of practice for a couple of years. I used to code in a really functional manner but I'm trying to get my head around object-orientated programming.
Preamble aside, I have an issue where after creating an instance of a class, my class variable is no longer being defined. I've made 2 versions of this which I'll use to demonstrate since I'm finding it hard to articulate.
Below I created a "character" class which I intended to use as a basis for both player characters and npcs. In the first draft I was updating this class, before realising it was going to affect subclasses, when I really just wanted it as a template. Either way, this particular code block worked; it adds the values of 2 dictionaries together, then assigns them to character.characterStats. It then prints them as per displayStats().
from collections import Counter
class character:
def __init__(self, *args, **kwargs):
pass
def __setattr__(self, name, value):
pass
characterRace = ''
characterStats = {}
charLocation = ''
charName = ''
class race:
def __init__(self):
pass
baseStatsDict = {
'Strength' : 5,
'Agility' : 5,
'Toughness' : 5,
'Intelligence' : 5 }
humanStatsDict = {
'Strength' : 1,
'Agility' : 1,
'Toughness' : 1,
'Intelligence' : 1 }
def displayRace():
print("Race: ", character.characterRace, "\n")
def displayStats():
for stat, value in character.characterStats.items():
print(stat, "=", value)
print("\n")
def raceSelection():
playerInput = input("I am a ")
playerInput
playerLower = playerInput.lower()
while "human" not in playerLower:
if "human" in playerLower:
character.characterStats = dict(Counter(race.baseStatsDict)+Counter(race.humanStatsDict))
character.characterRace = 'Human'
break
playerInput = input()
playerInput
playerLower = playerInput.lower()
playerChar = character()
raceSelection()
displayRace()
displayStats()
And this was the output:
Race: Human
Strength = 6
Agility = 6
Toughness = 6
Intelligence = 6
This however is the new code when I tried to tidy it up and turn the class into the template it was meant to be, and started using the class instance playerChar which for whatever reason can't assign the new value to playerChar.characterStats. playerChar.displayStats() prints the characterRace and characterStats variables as empty, even though they are assigned when the player enters the value human.
from collections import Counter
class character:
characterRace = ''
characterStats = {}
def __init__(self):
pass
def displayRace(self):
print("Race: ", self.characterRace, "\n")
def displayStats(self):
for stat, value in self.characterStats.items():
print(stat, "=", value)
print("\n")
class race:
def __init__(self):
pass
baseStatsDict = {
'Strength' : 5,
'Agility' : 5,
'Toughness' : 5,
'Intelligence' : 5 }
humanStatsDict = {
'Strength' : 1,
'Agility' : 1,
'Toughness' : 1,
'Intelligence' : 1 }
def raceSelection():
playerInput = input("I am a ")
playerInput
playerLower = playerInput.lower()
while "human" not in playerLower:
if "human" in playerLower:
playerChar.characterStats = dict(Counter(race.baseStatsDict)+Counter(race.humanStatsDict))
playerChar.characterRace = 'Human'
break
playerInput = input()
playerInput
playerLower = playerInput.lower()
playerChar = character()
raceSelection()
playerChar.displayRace()
playerChar.displayStats()
So this will output:
Race:
\n
\n
\n
So I know it's able to draw from the class race dictionaries and add their contents together as from the previous code. If I try and print the player.x characteristics it won't throw any errors so it recognises they exist. If anyone could explain to me what's going wrong and why in this new iteration, I'd be very grateful.
EDIT: So a friend and I have tried passing the class as an argument of raceSelection(), we've tried printing a string after each call/update of a variable and we've tried entering a string into the variable, printing it, then redefining the variable with a new string.
Input:
class character:
charRace = ''
charStats = {}
charLocation = ''
charName = ''
charString = "Cole said define a string."
Within the if statements:
if "human" in playerLower:
print("Oh, you're just a really ugly human.")
playerChar.charStats = dict(Counter(race.baseStatsDict)+Counter(race.humanStatsDict))
playerChar.charRace = 'Ugly Human'
print("playerChar.charString = ", playerChar.charString)
playerChar.charString = "Redefine."
print("playerChar.charString = ", playerChar.charString)
break
Output:
Oh, you're just a really ugly human.
playerChar.charString = Cole said define a string.
playerChar.charString = Cole said define a string.
Race:
It should not be character.characterStats.items(), but self.characterStats.items(). Similarly for all other values that belong to one, specific character.
Using the name of the class assigns a value that belongs to the class, and is the same for all objects you create. Lookup instance vs class attributes.
So, after trying to move the variables in and out of __init__, trying setattr(), trying to pass any sort of argument through the class just so it had some data, trying to run the instance of the class through a function, none of those solutions came to work in the end.
The solution turned out to be to create a subclass of character and manipulate that instead. I figured this would be alright as well since the player character will mutate throughout gameplay, and will never see further subclasses of itself.
class Main():
def __init__(self):
def placeName(self):
place_name = raw_input("\n=> Enter a place name: ")
placename_data = place_name.strip()
if re.match("^[a-zA-Z]*$", placename_data):
return placename_data
else:
print("Error! Only Alphabets from are allowed as input!")
a = Main()
new = a.placeName()
Above code for placeName() method runs correctly without using class but when I try to add it in a class, code gives an attribute error . Can't understand what is wrong here.
You don't need to define __init__ inside the Main class.
class Main():
def placeName(self):
place_name = raw_input("\n=> Enter a place name: ")
placename_data = place_name.strip()
if re.match("^[a-zA-Z]*$", placename_data):
return placename_data
else:
print("Error! Only Alphabets from are allowed as input!")
a = Main()
new = a.placeName()
Please remove __init__ method and try.
I am just learning classes in Python and for the past day I am stuck with the below.
I am trying to use a user input (from the main() function) to change the value of an attribute in the class.
I have been throught the #property and #name.setter methods that allow you to change the value of a private attribute.
However I am trying to find out how you can use user input to change the value of an attribute that is not private.
I came up with the below but it does not seem to work. The value of the attribute remains the same after I run the program. Would you have any ideas why?
class Person(object):
def __init__(self, loud, choice = ""):
self.loud = loud
self.choice = choice
def userinput(self):
self.choice = input("Choose what you want: ")
return self.choice
def choiceimpl(self):
self.loud == self.choice
def main():
john = Person(loud = 100)
while True:
john.userinput()
john.choiceimpl()
print(john.choice)
print(john.loud)
main()
In choiceimpl you are using == where you should use =.
Like stated before, you are using a comparison with == instead of the =.
Also you are returning self.choice in userinput as a return value, but never use it, because you set self.choice equal to input.
Shorter example:
class Person:
def __init__(self, loud):
self.loud = loud
def set_loud(self):
self.loud = input("Choose what you want: ")
def main():
john = Person(100)
while True:
john.set_loud()
print(john.loud)
main()
1) Change: '=='(comparison operator) to '='(to assign)
2) Inside class:
def choiceimpl(self,userInp):
self.loud = self.userInp
3) Outside class
personA = Person(loud) # Create object
userInp = raw_input("Choose what you want: ") # Get user input
personA.choiceimpl(userInp) # Call object method
I'm learning python with learn python the hard way and I'm making a 'game' using dict and classes. The code is incomplete, but the main problem is the AttributeError.
I'm stuck with this error:
Traceback (most recent call last):
File "juego.py", line 86, in <module>
juego.play()
File "juego.py", line 60, in play
game.enter()
AttributeError: 'NoneType' object has no attribute 'enter'
The code:
class entry(): #OK
def enter(self):
print 'Llegaste a la primera habitacion, miras a tu alrededor...'
print 'y ves un boton rojo en la pared...'
print 'Que haces?'
print 'Apretas el boton?'
print 'O seguis mirando?'
boton_rojo = raw_input('> ')
if 'boton' in boton_rojo:
print 'Apretas el boton y...'
print 'Aparece una puerta adelante tuyo!'
return 'Rescate_Prisionero'
elif 'mir' in boton_rojo:
print 'Seguis mirando...'
print '...'
print 'no encontras nada y decidis apretar el boton rojo'
print 'Apretas el boton y...'
print 'Aparece una puerta adelante tuyo!'
else:
print 'eh? que dijiste?'
class rescate_prisionero():
def enter(self):
print 'parece que si'
return 'Mago_Poderoso'
class mago_poderoso():
def enter(self):
print 'trolo'
return 'Pelea_esqueleto'
class pelea_esqueleto():
def enter(self):
print 'esque'
return 'Habitacion_Vacia'
class habitacion_vacia():
def enter(self):
print 'vac'
return 'Final_Scene'
class final_scene():
def enter(self):
print 'parece que esta todo bien'
class Engine(object):
def __init__(self, primer_escena):
self.primer_escena = primer_escena
def play(self):
ultima_escena = Map.Escenas.get('Final_Scene')
game =self.primer_escena.arranque().enter()
while game != ultima_escena:
game = Map.Escenas.get(game)
game.enter()
class Map():
def __init__(self, primer_escena):
self.primer_escena = primer_escena
def arranque(self):
inicio = Map.Escenas.get(self.primer_escena)
return inicio
Escenas = { 'Entry' : Entry(),
'Rescate_Prisionero' : rescate_prisionero(),
'Mago_Poderoso' : mago_poderoso(),
'Pelea_esqueleto' : pelea_esqueleto(),
'Habitacion_Vacia' : habitacion_vacia(),
'Final_Scene' : final_scene()
}
pepe = Map('Entry')
juego = Engine(pepe)
juego.play()
EDIT: sorry, I forgot the error, the code is NOW complete
You're getting this error because at some point game becomes the None object. This can happen at a number of different steps, so it might be hard to track down. Any time you call dict.get you are returning None if the key isn't found.
It's probably easiest to change all your dict.get(key) statements to dict[key] statements. There doesn't appear to be any way to proceed if the dictionary doesn't contain the key, so throwing a KeyError is definitely better than suppressing the error until later.
It's also possible that one or more of your Map.Escenas values are actually None, so even if dict.get is finding the value, it's returning a None. This is why using dict[key] is helpful here -- at least you can narrow it down! You didn't include any of the code from any of the functions:
Entry
rescate_prisionero
mago_poderoso
pelea_esqueleto
habitacion_vacia
final_scene
So there's no way for us to check that here.
I've been trying to write a simple program in python to use classes and test attributes. It asks the user to input one of the names, and uses that input to display 2 attributes of the name. I've tried to include a try...except block to catch the NameError that occurs when typing something that hasn't been defined as the name of an object, but I still get this traceback:
Traceback (most recent call last):
File "C:/Users/Bede/Documents/Technology/Programming/Python/276/testcode", line 18, in <module>
animalName = input(">")
File "<string>", line 1, in <module>
NameError: name 'Marmadukke' is not defined
I'm aware this probably isn't the best way to do things, so I'm open to all suggestions.
My full code is here:
class Dog(object):
def __init__(self,name,chasesCats):
self.name = name
self.chasesCats = chasesCats
class Cat(object):
def __init__(self,name,chasesMice):
self.name = name
self.chasesMice = chasesMice
Marmaduke = Cat("Marmaduke",True)
Timmy = Cat("Timmy",False)
Cerberus = Dog("Cerberus",True)
Max = Dog("Max",False)
print("Enter Marmaduke, Timmy, Max or Cerberus.")
animalName = input(">")
while 1:
try:
if isinstance(animalName,Cat):
print("Cat")
if animalName.chasesMice:
print("Chases mice")
else: print("Doesn't chase mice")
if isinstance(animalName,Dog):
print("Dog")
if animalName.chasesCats:
print("Chases cats")
else: print("Doesn't chase cats")
break
except NameError:
print("Try again!")
I'm guessing you're using python2.x. In that case, you should use raw_input instead of input. The problem is that on python2.x, input calls eval on the data you put in. I suppose, this means that you could put in the data as "Marmaduke" (note the quotes). But having the program behave differently depending on whether you're using python2.x or 3.x seems undesirable.
An easy way to make the code work for both, python2.x and python3.x:
try:
raw_input
except NameError:
raw_input = input
animalName = input(">") is outside of the try block. So the Error won't be caught.
Probably you want that inside the try block in the loop:
while 1:
try:
animalName = input(">")
if isinstance(animalName,Cat):
This line is the culprit:
animalName = input(">")
When you enter Marmadukke, which isn't defined yet, you get the name error, since you're trying to do:
animalName = Marmadukke #Not defined.
Wrap it in a try/except block:
try:
animalName = input(">")
except:
print("Invalid input!")
But to achieve this, it would be much better to store your animals to a dictionary, and retrieve only the name:
animals = {}
animals['Marmaduke'] = Cat("Marmaduke",True)
animals['Timmy'] = Cat("Timmy",False)
animals['Cerberus'] = Dog("Cerberus",True)
animals['Max'] = Dog("Max",False)
And to retrieve:
animalName = animals[raw_input(">")]
You can then put it inside your while function, and catch KeyError instead of NameError.
Hope this helps!
For the fun and interest, I have extended your code; try tracing through it, you should learn lots ;-)
class Mammal(object):
index = {}
def __init__(self, name, chases_what=type(None)):
Mammal.index[name] = self
self.name = name
self.chases_what = chases_what
def speak(self):
pass
def chase(self, who):
if isinstance(who, self.chases_what):
self.speak()
print('{} chases {} the {}'.format(self.name, who.name, who.__class__.__name__))
who.speak()
else:
print("{} won't chase a {}".format(self.name, who.__class__.__name__))
class Mouse(Mammal):
def speak(self):
print('Squeak! Squeak!')
class Cat(Mammal):
def __init__(self, name, chases=True):
super(Cat, self).__init__(name, Mouse)
self.chases = chases
def chase(self, who):
if self.chases:
super(Cat, self).chase(who)
else:
print("{} won't chase anything".format(self.name))
class Dog(Mammal):
def __init__(self, name, chases_what=Cat):
super(Dog, self).__init__(name, chases_what)
def speak(self):
print('Bark! Bark!')
def chase(self, who):
if self is who:
print("{} chases his own tail".format(self.name))
else:
super(Dog, self).chase(who)
# create animal instances
Mouse('Jerry')
Mouse('Speedy Gonzalez')
Cat('Garfield', chases=False)
Cat('Tom')
Dog('Max')
Dog('Marmaduke', (Cat, Mouse))
def main():
while True:
name = raw_input('Enter an animal name (or Enter to quit): ').strip()
if not name:
break
me = Mammal.index.get(name, None)
if me is None:
print("I don't know {}; try again!".format(name))
continue
chase = raw_input('Enter who they should chase: ').strip()
target = Mammal.index.get(chase, None)
if target is None:
print("I don't know {}".format(name))
else:
me.chase(target)
if __name__=="__main__":
main()