[Tutor] Object and Attribute Error

Alan Gauld alan.gauld at yahoo.co.uk
Fri Mar 27 21:25:40 EDT 2020


On 27/03/2020 21:49, Alan Thwaits wrote:
> Another error message in my game script from Exercise 43 in Zeb Shaw's
> "Learn Python the Hard Way."

I'm assuming you are only sending us a fraction of the code because
otherwise you should be getting many more errors before reaching that line.


> class Engine(object):
> 
>     def __init__(self, scene_map):
>         self.scene_map = scene_map
> 
>     def play(self):
>         current_scene = self.scene_map.opening_scene()
>         last_scene = self.scene_map.next_scene('finished')
> 
>         while current_scene != last_scene:
>             next_scene_name = current_scene.enter()

This is where the error is reported and it says current_scene
is None.

So where is current scene defined? In the line above
where Map.opening_scene() is called...

>     def opening_scene(self):
>         return self.next_scene(self.start_scene)

Which is just a wrapper for Map.next_scene()

>     def next_scene(self, scene_name):
>         val = Map.scenes.get(scene_name)
>         return val


which returns the result from scenes.get()
scenes is a dictionary,
and dict.get returns None when it cannot find the
requested key.

This is where we start guessing because we cannot
see the code. The call to enter() presumably returns
the name of the next scene, and so on to the end of
the dict?

Presumably one of the enter methods returns an invalid
key? But without seeing the enter methods we cant tell.

> class Map(object):
> 
>     scenes = {
>         'central_corridor': CentralCorridor(),
>         'laser_weapon_armory': LaserWeaponArmory(),
>         'the_bridge': TheBridge(),
>         'escape_pod': EscapePod(),
>         'death': Death(),
>         'finished': Finished(),
>     }

This is instantiating a bunch of classes which we can't see
so I assume they are defined elsewhere? And that they all
have enter() methods.

>   File "C:/Users/Alan/Documents/Python/ex43.py", line 29, in play
>     next_scene_name = current_scene.enter()
> 
> AttributeError: 'NoneType' object has no attribute 'enter'
> 
> Obviously, I need to understand object and attribute better. Any guidance
> would be appreciated.

classes are type definitions.
objects are instances of classes.
attributes are the names inside the classes/objects.

A return value of None from the get() method is a NoneType object.
NoneType objects do not have an attribute(aka name) called enter
so you get an error

You can check the attributes of an object with the dir function:

>>> dir(None)
['__bool__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
'__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__']

So while None has a bunch of names they are all "hidden"(ie they
have __ in front - sometimes called dunder.) Most are oprerationds.
But nothing you can call by name, and certainly no enter()

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list