How to call a stat from a class into a function - Python - python

I am struggling to create a health/anger (variables) drop when making the user fight a knight. I have defined a class called kingsmen, that is very simple and used for each knight, but I keep getting told that I am not calling the class properly. I'm not sure how to explain it. Below is the code for the class and for the knight, and the error message will be at the bottom. Some of the print spacing is weird (the ones with ''' ''') because the site is being difficult.
Thank you!
Class:
class kingsmen:
def __init__(self):
self.stats = {}
def attributes(self):
health=15
anger=7
self.stats["health"] = 15 #storing default health count
self.stats["anger"] = 7
return self.stats
def warning(self): #players will see this message when meeting a knight
print ('A kingsmen! Prepare for battle!')
def noise(self):
print ("H e y , i t ' s a v i l l a g e r !") #have these attributes later.
def death(self):
if healh == 0:
print ('''DEFEATED''')
Knight:
def rknightOne(kingsmen): #r stands for random, he will be one of 5 random villains you can face
rknightOne=kingsmen()
#while health in kingsmen.stats()!= 0 and anger != 0:
if action == 'attack':
for health in rknightOne.attributes:
health=health-1
print health
print_slowly ('I did not feel a thing. Ha ha ha!')
healthDrop(user)
elif action == 'mercy':
for anger in rknightOne.attributes:
anger=anger-1
print_slowly ('Huh. I feel something warm inside.')
elif action=='run':
print_slowly ('Not so fast!')
else:
print_slowly ("Jeez this guy is looney. I CAN'T UNDERSTAND YOU!")
Error:
Traceback (most recent call last):
File "C:/Python27/REDEMPTION/Redemption Game V1.py", line 678, in <module>
print randomKnight()
File "C:/Python27/REDEMPTION/Redemption Game V1.py", line 440, in randomKnight
print random.choice([rknightOne(kingsmen), rknightTwo(kingsmen), rknightThree(kingsmen), rknightFour(kingsmen), rknightFive(kingsmen)])
File "C:/Python27/REDEMPTION/Redemption Game V1.py", line 178, in rknightOne
for health in rknightOne.attributes:
TypeError: 'instancemethod' object is not iterable
The random function it's talking about is just cycling through 5 knights that could pop up. This is the code in case it's helpful:
def randomKnight():
print random.choice([rknightOne(kingsmen), rknightTwo(kingsmen), rknightThree(kingsmen), rknightFour(kingsmen), rknightFive(kingsmen)])

Change this
for health in kingsmen.stats():
with one of the following statements
for health in kingsmen.stats: # if you don't want to call the method
for health in kingsmen.stats(some_argument): # or if you want to call the method provide arguments
Reason you are getting this error is that you have defined both
self.stats = {}
and
def stats(self)
in kingsmen class, so it's confusing you.

With the latest revision of your code, it is clear what you are trying to do now. The error message you are seeing is telling you that you cannot iterate over an instance method. That is exactly what you are trying to do. You are trying to loop over kingsmen.attributes which is a method in your class. You cannot do that. Your method is actually returning a dictionary, and the result of executing that method is something you can iterate over. So you actually want to iterate over the result of calling attributes(). However, there is one more problem to clear up before that as I'll explain below.
In order to be able to properly call attributes, you have to instantiate your class (documentation on classes and objects in Python) first.
What you are doing is not executing the method, furthermore, not instantiating the class to be able to access and execute the method.
To resolve this, your line here:
for health in kingsmen.attributes:
You need to first instantiate your class, and then use the object from your class to call the attributes method. The return of that attributes method as you implemented will return the dictionary that you are trying to iterate over. So, your code should look like this:
my_kingsmen = kinsgmen()
for health in my_kinsgmen.attributes():

Related

How to update variables passed between classes?

I'm trying to pass variables between different classes. In order to accompish this task, I have created an info class (here called 'declaration') so that the code reads:
class declaration():
def __init__(self):
self.info1 = 999
self.info2 = 'something_else'
print ('At declaration ')
class controller():
def __init__(self):
instance = declaration()
print ('Initial number ',instance.info1, instance.info2)
modifier(declaration)
print ('MIDDLE ',instance.info1,declaration.info1)
instance = declaration()
print ('Final number ',instance.info1)
class modifier():
def __init__(self,aux):
print ('MODIFIER')
self.info=aux
self.info.info1=55555
controller()
The output is:
At declaration
Initial number 999
something else
MODIFIER
MIDDLE 999 55555
At declaration
Final number 999
However, I'm not really sure about some of the inners of the code. I have one major question and a minor one. My main question is that when the class 'modifier' is modified according to:
class modifier():
def __init__(self,aux):
self.info=aux
print ('MODIFIER',self.info.info1)
self.info.info1=55555
it produces the error AttributeError: type object 'declaration' has no attribute 'info1' [Flipping the last 2 lines fixes the error]. It's confusing (at least to me) whether the class attributes are not passed or they have to be reinitialized.
The second question is how to update instance once its class has been updated. The second call to instance = declaration() seems to accomplish nothing.
Quick side note: Yes I do realise, I just want to say please try to follow the PEP8 python guide as it makes your code look cooler (and easier to read) and all the cool kids use it.
There are a few things wrong with your code, calling modifier(declaration) actually makes the aux parameter an uninitilized class, you want to call modifier(instance) as the init function has already been ran.
Also it would be easier to drop the self.info = aux as you can just call aux.info1 and it looks cleaner and is actually faster (Because you are calling one less Fast Store command in bytecode).
Lastly at print ('MIDDLE ',instance.info1,declaration.info1) you again parse declaration uninitilized therefore you get the error AttributeError: type object 'declaration' has no attribute 'info1', to fix this simply put declaration().info1 as that calls the init function (it is the same as saying declaration.__init__().info1).
So finally you get:
class declaration():
def __init__(self):
self.info1 = 999
self.info2 = 'something_else'
print ('At declaration ')
class controller():
def __init__(self):
instance = declaration()
print ('Initial number ', instance.info1, instance.info2)
modifier(instance)
print ('MIDDLE ', instance.info1, declaration().info1)
instance = declaration()
print ('Final number ',instance.info1)
class modifier():
def __init__(self, aux):
print ('MODIFIER')
aux.info1 = 55555
controller()
Hope this helped.

AttributeError: 'NoneType' object has no attribute 'print_Toy'

I am having a very simple code of python, wherein I am creating an object array in the constructor, But whenever I try calling a display function to see all the objects in the Object Array, it returns this NoneType exception.
Class called Toy is the actual object class, which is shown below:
class Toy:
__name=None
__cost=None
def __init__(self,name,cost):
self.__name=name
self.__cost=cost
def get_Name(self):
return self.__name
def get_Cost(self):
return self.__cost
def print_Toy(self):
print(" Name of the toy: ",self.__name)
print(" Cost of the toy: ",self.__cost)
The below-shown class Toy_Bag contains the object array, which I am initializing in the constructor.
from Toy import Toy
class Toy_Bag:
__toys=[None]
def __init__(self, no_of_toys):
self.__create_Toy_bag(no_of_toys)
def __create_Toy_bag(self, no_of_toys):
name,cost= None,0
for toy in range(0, no_of_toys):
print("\n Enter the name of the toy: ",end="")
name=input()
print("\n Enter the cost of the toy: ",end="")
cost=int(input())
toy=Toy(name,cost)
self.__toys.append(toy)
self.print_Toy_Bag()
def print_Toy_Bag(self):
for toy in self.__toys:
toy.print_Toy()
Traceback (most recent call last):
File "Main.py", line 9, in <module>
toy_bag=Toy_Bag(3)
File "C:\Users\SONY\Desktop\Python Scripts\Tools\Toy_Bag.py", line 8, in __init__
self.__create_Toy_bag(no_of_toys)
File "C:\Users\SONY\Desktop\Python Scripts\Tools\Toy_Bag.py", line 19, in __create_Toy_bag
self.print_Toy_Bag()
File "C:\Users\SONY\Desktop\Python Scripts\Tools\Toy_Bag.py", line 23, in print_Toy_Bag
toy.print_Toy()
AttributeError: 'NoneType' object has no attribute 'print_Toy'
C:\Users\SONY\Desktop\Python Scripts\Tools>
Any help is highly appreciated.
You are initializing your list with one element of None right here:
class Toy_Bag:
__toys=[None]
then you add more toys inside def __create_Toy_bag(self, no_of_toys) - will be at position 1 to n inside your list. The first stays None.
If you print your __toys you call a method of your Toy-class with this first None.
Change it to
__toys=[]
so
def print_Toy_Bag(self):
for toy in self.__toys: # first element is no longer None
toy.print_Toy()
does no longer get the first element as None.
You might want to give How to debug small programs (#1) a read -it helps you debug your own programs. If you are interested in how to name stuff "correctly": PEP-008: Style Guide is a great read as well (spacing, private members and a lot of other stuff covered in it).

PYTHON: AttributeError: 'int' object has no attribute 'hand'

So I have an exercise on python - building a BlackJack game.
I have started with defining how every phrase of the game would go.
Now when I run this code below, In case the input is '0' - which means you don't want cards anymore, it runs perfectly. But when the input is '1' - which means you want to pick card, I get an error:
Traceback (most recent call last):
File "C:/Users/Maymon/PycharmProjects/untitled4/BlackJack.py", line 1, in <module>
class blackjack(object):
File "C:/Users/Maymon/PycharmProjects/untitled4/BlackJack.py", line 34, in blackjack
player(1)
File "C:/Users/Maymon/PycharmProjects/untitled4/BlackJack.py", line 25, in player
PickCard(1)
File "C:/Users/Maymon/PycharmProjects/untitled4/BlackJack.py", line 18, in PickCard
self.hand+= random.randrange(1, 13)
AttributeError: 'int' object has no attribute 'hand'
The code:
class blackjack(object):
#this func defines how player should react
def player(self):
#this func defines what case of technical loosing
def loser():
print("You have reached", hand , ". Which is beyond 21. Therefor, you have lost the game. Better luck next time!")
#this func is responsible for picking card issue.
def PickCard(self):
import random
x=1
while x == 1:
pick = int(raw_input("Enter 1 if you want another card, else Enter 0"))
if pick == 1:
self.hand = self.hand + random.randrange(1, 13)
else:
x=0
import random
print "Now your first card will automatically be given to you:"
hand=random.randrange(1,13)
print "hand: ", hand
PickCard(1)
print hand
if hand>21:
loser()
elif hand==21:
pass
else:
pass
player(1)
Thanks in advance.
You are making the function call as player(1) where the player function expects the argument as of self type .i.e. instance of the class blackjack. Hence, while doing self.hand = self.hand + random.randrange(1, 13) it is throwing the above mentioned error.
I think you do not want to make a call to player() function from within the class, Is it? Move that part to outside the class. Firstly create the object of class blackjack (Note: In Python, class names should be defined as CamelCase variables like: BlackJack). For example:
blackjack_obj = blackjack()
Then call the player() function as:
blackjack_obj.player()

'NoneType' object has no attribute

I'm getting an error about 'NoneType' object has no attribute.... How do I resolve it?
def fight(self, pMonstername):
print ("The fight begin")
MonInList = self.monsterSearch(pMonstername)
#at first I have the method "Fight" where i build a temp variable MonInList
#which I declare with the help of the methode "monsterSearch"
def monsterSearch(self, pMonstername):
for m in self.monsterList:
if m.name == pMonstername:
return m
#in this method I go through step by step through the monsterList, in which
#are objects of type Monster are stored and pick out those monster which has
#the same name as those I search for and this object should be returned
if self.player.getStrength() > MonInListe.getStrength:
#later I want to compare the strength of the player and the Monster, which i
#declared before, but then there is the error:
AttributeError: 'NoneType' object has no attribute 'getStrength'
The Short Answer
The short answer to this question is that the error AttributeError: 'NoneType' object has no attribute 'getStrength' suggests that you have self.player = None in the __init__() of the class that contains your conditional if self.player.getStrength() > ..., but it wasn't properly updated to be something else (perhaps an instance of class Player?) before the conditional.
There are some other problems and errors that this will trigger, but this is the place where I would start to try to debug things.
The Long Answer
Another important thing to watch out for is that just because you've included the method in your class doesn't mean it will automatically run. The fact that you are running into the error that you described, and not one of the other errors I think I see in your code, suggests that the methods are either not being called in the correct order to be properly used in your comparison, or are not called at all. This is why I think the Player class was simply not being called correctly.
To give an example, see the code block below. It is a variation of what was provided in the question, and if it is run it will reproduce the problem. First the classes and methods:
# The post author mentioned there objects of the type Monster
# stored in a list in the main class.
# Using the main monster characters from Monsters Inc,
# below are hastily constructed classes to attempt to reproduce the issue.
class Sully(object):
def __init__(self):
self.name = "James P. Sullivan"
self.getStrength = 10
class Player(object):
def getStrength(self):
return 100
class SomeClass(object):
def __init__(self):
self.monsterList = [Sully]
self.player = None
def fight(self, pMonstername):
#at first I have the method "Fight" where i build a temp variable MonInList
#which I declare with the help of the methode "monsterSearch"
print ("The fight begin")
MonInList = self.monsterSearch(pMonstername)
def monsterSearch(self, pMonstername):
#in this method I go through step by step through the monsterList, in which
#are objects of type Monster are stored and pick out those monster which has
#the same name as those I search for and this object should be returned
for m in self.monsterList:
if m.name == pMonstername:
return m
def compareStrength(self):
#later I want to compare the strength of the player and the Monster, which i
#declared before, but then there is the error:
if self.player.getStrength() > MonInListe.getStrength:
print("Success!")
# AttributeError: 'NoneType' object has no attribute 'getStrength'
Next, let's create an instance of SomeClass and then run the compareStrength method:
s = SomeClass()
s.compareStrength()
The result is this error, the stack provided in full:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-71-bfa22232a4a7> in <module>()
1 s = SomeClass()
----> 2 s.compareStrength()
<ipython-input-70-3a4fe2cd3c3c> in compareStrength(self)
42 #later I want to compare the strength of the player and the Monster, which i
43 #declared before, but then there is the error:
---> 44 if self.player.getStrength() > MonInListe.getStrength:
45 print("Success!")
46 # AttributeError: 'NoneType' object has no attribute 'getStrength'
AttributeError: 'NoneType' object has no attribute 'getStrength'
What's interesting about this is that this should NOT have been the first error that was triggered. I would have expected this error instead:
The fight begin
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-79-5009b509291a> in <module>()
1 s = SomeClass()
----> 2 s.fight("James P. Sullivan")
3 s.compareStrength()
<ipython-input-77-13d18f4abe98> in fight(self, pMonstername)
29 #which I declare with the help of the methode "monsterSearch"
30 print ("The fight begin")
---> 31 MonInList = self.monsterSearch(pMonstername)
32
33 def monsterSearch(self, pMonstername):
<ipython-input-77-13d18f4abe98> in monsterSearch(self, pMonstername)
36 #the same name as those I search for and this object should be returned
37 for m in self.monsterList:
---> 38 if m.name == pMonstername:
39 return m
40
AttributeError: type object 'Sully' has no attribute 'name'
...which would be caused by running this code:
s = SomeClass()
s.fight("James P. Sullivan")
s.compareStrength()
I think s.fight() should have been called and triggered this error because otherwise the MonInList would not be correct when we run compareStrength(). It's for this reason that I think simply reviewing the order in which the methods are being called will fix the main issue in the question, which is why I included it here (even though it seems tangential).
Oh, and by the way, the fix for the latest issue described would be to change the line if m.name == pMonstername: to if m().name == pMonstername:
Hope that helps!
Ok, so it seems that your object 'MonInListe' has not been instantiated before being used. It then gets to be 'None' and effectively has no attribute.
You should check elsewhere in your code (not in the shown part of it here) for the correct instantiation of this object 'MonInListe'.
The origin of the error you are encountering is definitively not contained in the part of the code you expose here.

Get the return value from a function in a class in Python

I am trying to simply get the value out of my class using a simple function with a return value, I'm sure its a trivial error, but im pretty new to python
I have a simply class set up like this:
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(num):
self.score = num
# Enemy Info
def getEnemies():
return self.num_enemies
# Lives Info
def getLives():
return self.getLives
etc.....
Than I create an instance of the class as such:
scoreObj = score()
for enemies in range(0, scoreObj.getEnemies):
enemy_sprite.add(enemy())
I get the error saying that an integer is expected, but it got an instancemethod
What is the correct way to get this information?
Thanks!
scoreObj.getEnemies is a reference to the method. If you want to call it you need parentheses: scoreObj.getEnemies().
You should think about why you are using a method for this instead of just reading self.num_enemies directly. There is no need for trivial getter/setter methods like this in Python.
The first parameter for a member function in python is a reference back to the Object.
Traditionally you call it "self", but no matter what you call the first parameter, it refers back to the "self" object:
Anytime I get weird errors about the type of a parameter in python, I check to see if I forgot the self param. Been bit by this bug a few times.
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(self, num):
self.score = num
# Enemy Info
def getEnemies(self):
return self.num_enemies
# Lives Info
def getLives(foo): #foo is still the same object as self!!
return foo.num_lives
#Works but don't do this because it is confusing
This code works:
class score():
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
def setScore(self, num):
self.score = num
def getEnemies(self):
return self.num_enemies
def getLives(self):
return self.getLives
scoreObj = score()
for enemy_num in range(0, scoreObj.getEnemies()):
print enemy_num
# I don't know what enemy_sprite is, but
# I commented it out and just print the enemy_num result.
# enemy_sprite.add(enemy())
Lesson Learned:
Class functions must always take one parameter, self.
That's because when you call a function within the class, you always call it with the class name as the calling object, such as:
scoreObj = score()
scoreObj.getEnemies()
Where x is the class object, which will be passed to getEnemies() as the root object, meaning the first parameter sent to the class.
Secondly, when calling functions within a class (or at all), always end with () since that's the definition of calling something in Python.
Then, ask yourself, "Why am I not fetching 'scoreObj.num_lives' just like so instead? Am I saving processing power?" Do as you choose, but it would go faster if you get the values directly from the class object, unless you want to calculate stuff at the same time. Then your logic makes perfect sense!
You made a simple mistake:
scoreObj.getEnemies()
getEnemies is a function, so call it like any other function scoreObj.getEnemies()

Categories

Resources