Python is raising the below exception when running my script. Could somebody please explain why this is happening and how to fix it?
Traceback (most recent call last):
File "C:\Users\vinsunny\AppData\Local\Programs\Python\Python36\test.py", line 28, in <module>
test.my_func()
File "C:\Users\vinsunny\AppData\Local\Programs\Python\Python36\test.py", line 23, in my_func
print('non secret no. from test_func: ', self.number2)
AttributeError: 'Test' object has no attribute 'number2'"
class Test():
__class_secret_number = 100
def __secret_func(self):
self.number1 = 1
self.__secret_number1 = 11
print('You cannot see this unless accessing from the Class itself')
def test_func(self):
self.number2 = 2
self.__secret_number2 = 22
def my_func(self):
self.__secret_func()
print('Secret no. from class: ', self.__class_secret_number)
print('non secret no. from secret func: ', self.number1)
print('Secret no. from secret func: ', self.__secret_number1)
# These two prints raise an exception.
print('non secret no. from test_func: ', self.number2)
print('Secret no. from test_func: ', self.__secret_number2)
test = Test()
test.my_func()
At the time the offending print statement is executed, the number2 attribute on your Test instance has not been defined.
The first time the number2 attribute gets set is in the test_func() method. i.e. Attempting to access number2 before calling test_func() will result in the error you are observing.
You should assign a default value to self.number2 in the initializer for the Test class. You could also call test_func() before calling my_func(). But, either way, it's still good practice to initialize all instance attributes in Test.__init__.
The interpreter will raise an exception for the same reason when you try to access the undefined attribute __secret_number_2 in my_func().
test_func is never called, so number2 and __secret_number2 doesn't exist.
Need to call the function before try to access them, or init them with init method.
Related
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).
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.
I'm doing a game in pygame and what I'm trying to do, is to make an entity target another.
When I call the target function, I get "TypeError: NoneType object is not callable" What I understood after doing research on this error, is that it occurs, when you try to use the return value of a function that hasn't any.
But, my function isn't supposed to return something and I don't use a return value, so I'm a bit out of ideas.
I hope someone can help me, here is my code:
target function
def target(self,x,y):
target = self.world.getPointEntity(x,y)
if target != None and target.get_itarget():
self.set_target(target)
call to target function
self.player.target(x,y)
If you have any questions, feel free to ask.
EDIT: Code of getPointEntity function:
def getPointEntity(self, x, y, searchRange=24):
for entity in self.entities.itervalues():
if entity != None:
distance = entity.get_distance(x, y)
if distance < searchRange:
return entity
return None
As for the get_itarget function, it just returns True or False depending on the respective entity being a legal target or not.
The traceback points to line with self.player.target()
Full traceback:
__Main2.py", line 971, in <module>
Game(1920,1080)
__Main2.py", line 795, in __init__
self.run()
__Main2.py", line 910, in run
self.player.target(x,y)
TypeError: 'NoneType' object is not callable
EDIT: the method target belongs to the super class of the player class.
class Player(LivingEntity):
def __init__(self, name, world, image, x, y, speedModifier, sizeradius, inv_image, filler, shadow, scx, scy, animseq, animn):
LivingEntity.__init__(self, name, world, image, x, y, speedModifier, sizeradius, animseq, animn)
self.inventory = None
self.scx = scx
self.scy = scy
self.addInventory(inv_image, filler, shadow)
class LivingEntity(GameEntity):
def __init__(self, name, world, images, x, y, speedModifier, sizeradius, animseq, animn, xshift=48, yshift=48):
GameEntity.__init__(self, name, world, images, x, y, speedModifier, sizeradius, animseq, animn, xshift, yshift)
self.target = None
def set_target(self, target):
self.target = target
def target(self,x,y):
target = self.world.getPointEntity(x,y)
if target != None and target.get_itarget():
self.set_target(target)
I kind of solved the problem by putting the check for a target entity outside of the target function. I can't really see the differnce but it seems to work.
Inside the LivingEntity class you have a method called target, and the syntax used by code within the LivingEntity class to refer to that LivingEntity.target method is self.target. But inside the LivingEntity.set_target method you overwrite self.target with the self.target = target assignment.
After that assignment, the next time you call the target method Python tries to make the call using whatever set_target has set self.target to, instead of calling the LivingEntity.target method that you expect it to use.
So you got that error message because you told set_target to set self.target to None.
As PM 2Ring pointed out, set_target overwrites the LivingEntity.target field with whatever it gets. But the problem starts even before that: the __init__ method destroys the target method before anyone gets a chance to call it.
Here's a stripped-down example of what's happening:
#!/usr/bin/env python3
class InitDestroysMethod(object):
def __init__(self):
self.target = None
return
def target(self):
return "This is the InitDestroysMethod.target method."
def main():
print("Class with __init__ and target method:")
print("InitDestroysMethod.target: ", end="")
print(InitDestroysMethod.target)
print("InitDestroysMethod.target(): ", end="")
print(InitDestroysMethod.target(None)) # Bogus "self" argument.
print()
print("Instance with __init__ and target method:")
print("InitDestroysMethod().target: ", end="")
print(InitDestroysMethod().target)
print("InitDestroysMethod().target(): ", end="")
print(InitDestroysMethod().target())
return
if "__main__" == __name__:
main()
Below is the output of this program:
Class with __init__ and target method:
InitDestroysMethod.target: <function target at 0x1266490>
InitDestroysMethod.target(): This is the InitDestroysMethod.target method.
Instance with __init__ and target method:
InitDestroysMethod().target: None
InitDestroysMethod().target(): Traceback (most recent call last):
File "./init_vs_method.py", line 30, in <module>
main()
File "./init_vs_method.py", line 25, in main
print(InitDestroysMethod().target())
TypeError: 'NoneType' object is not callable
As you can see, the uninstantiated class does have a target method (technically just a function --- when an object is instantiated, it will have a bound method with the self parameter bound to the object). It can be called like any other function, as long as you provide an argument for the self parameter. (That trick only works in this case because target doesn't actually use its self parameter, but it lets me prove that there's a callable function named target.)
But an instance of the class has already suffered the effects of __init__. In this case, __init__ sets the value of target in the instance dictionary to None. The old value of target was a bound method, but by the time you get a reference to the newly-created and initialized object, that old value has long since been discarded.
When you use a field like some_instance.target, the search for an entity named "target" starts in the instance dictionary. That dictionary does indeed have a key named "target". That the class has a function also named "target" makes no difference --- the name has already been found, and its value (None) gets used.
Then you try to call that None value as if it were a function or a method, and you get a TypeError.
I wrote a code which is going to store occurrences of words from a text file and store it to a dictionary:
class callDict(object):
def __init__(self):
self.invertedIndex = {}
then I write a method
def invertedIndex(self):
print self.invertedIndex.items()
and here is how I am calling:
if __name__ == "__main__":
c = callDict()
c.invertedIndex()
But it gives me the error:
Traceback (most recent call last):
File "E\Project\xyz.py", line 56, in <module>
c.invertedIndex()
TypeError: 'dict' object is not callable
How can I resolve this?
You are defining a method and an instance variable in your code, both with the same name. This will result in a name clash and hence the error.
Change the name of one or the other to resolve this.
So for example, this code should work for you:
class CallDict(object):
def __init__(self):
self.inverted_index = {}
def get_inverted_index_items(self):
print self.inverted_index.items()
And check it using:
>>> c = CallDict()
>>> c.get_inverted_index_items()
[]
Also check out ozgur's answer for doing this using #property decorator.
In addition to mu's answer,
#property
def invertedIndexItems(self):
print self.invertedIndex.items()
then here is how you'll cal it:
if __name__ == "__main__":
c = callDict()
print c.invertedIndexItems
Methods are attributes in Python, so you can't share the same name between them. Rename one of them.
def buy():
while True:
items={"Armor": 25, "Sword": 25}
print("What do you want to buy?\n1/Armor +25 defense\t50 golds\n2/Sword +25 damage\t50 golds")
s1=input("Choose the item you want to buy (1 and/or 2 only): ")
try:
global a
a=int(s1)
if a in range (1,3):
break
except ValueError:
pass
buy()
print(a)
error message:
Traceback (most recent call last):
File "C:\code\work\The Role-Playing combat game.py", line 58, in <module>
print(a) NameError: global name 'a' is not defined
Line 58 is print(a)
I declared "a" as the global value, but somehow the interpreter gives me the error message. Please help, thanks.
Solved, declare "a" outside of the function first
Did you declare the a variable earlier in your code? Otherwise, calling global a before declaring it will throw that error. You need to put a = something before you call global a on it.