Reputation: 481
I'm three weeks into learning Python, via "Learn Python the Hard Way" -- since I'm not new to programming, I've been able to progress pretty rapidly through the first half of the book, until I started to get into the OOP portion with classes and objects. Now I'm having a lot of trouble; though I think I've understood the ideas behind these object concepts, I've clearly got something obscurely wrong with my code (I'm using Python 2.7.6, which appears to be part of gcc 4.8.2, in Kubuntu 14.04, kept up to date).
I'm working on Exercise 43, trying to create an adventure game starting from the author's skeleton class definitions. I did pretty well with the first game design (using Python the way I'd have used Basic for the same task, years ago), but I've been about ten console hours trying to beat the latest error in the OOP game; I've read dozens of searched solutions (here and elsewhere) without finding anything that precisely applies. I've pared the code down as much as possible, and I'm still seeing the same error (which I'll paste after the code -- warning, this is still almost 100 lines):
# Python the Hard Way -- Exercise 43: Basic Object-Oriented Analysis and Design
# received as skeleton code, try to make it into a playable game
# my comment: Much harder than designing from scratch! Author's
# design method (or that appropriate for OOP) differs greatly from
# what I'm used to.
from sys import exit
class UserEntry (object):
def __init__(self):
pass
def get_input (self):
# initialize variable for trimmed command list
short_list = []
# accept input, break at spaces, and reverse for parsing
command = raw_input ('> ')
command_list = command.split (' ')
command_list.reverse ()
# parse command here
for i in reversed (xrange (len(command_list))):
if ((command_list [i] in a_game.act.keys()) or
(command_list [i] in a_game.obj.keys())):
short_list.append (command_list.pop())
else:
command_list.pop()
# return parsed_command
if len(short_list) == 1 and short_list[0] in a_game.act.keys():
short_list.append (' ')
return short_list
class Scene (object):
def enter(self):
pass
class Engine (object):
def __init__(self, scene_map):
self.scene_map = scene_map
self.act = {
'inventory' :self.inventory,
'look' :self.look,
}
self.obj = {
'blaster' :'',
'corridor':'',
'gothon' :'',
}
def inventory(self):
pass
def look (self):
pass
def opening_scene(self):
# introduce the "plot"
print "Game intro",
def play(self):
entry = UserEntry()
self.opening_scene()
a_map.this_scene.enter()
class CentralCorridor(Scene):
def enter(self):
print "Central Corridor"
class Map(object):
def __init__(self, start_scene):
scenes = {
'central corridor': CentralCorridor,
}
this_scene = scenes[start_scene]()
print this_scene
a_map = Map('central corridor')
a_game = Engine(a_map)
a_game.play()
When I try to run this, I get the following:
$ python ex43bug.py
<__main__.CentralCorridor object at 0x7f13383c8c10>
Game intro
Traceback (most recent call last):
File "ex43bug.py", line 89, in <module>
a_game.play()
File "ex43bug.py", line 70, in play
a_map.this_scene.enter()
AttributeError: 'Map' object has no attribute 'this_scene'
Clearly, something is preventing this_scene
from being visible to other classes/methods; I just don't get what it is. I don't have indention problems (that I can see), I don't have circular imports (in fact, I'm importing only a single module, for the exit
command). The first print line is generated by print this_scene
within instance a_map
; I should get Game intro
and then Central corridor
as, first, Engine.opening_scene
and then CentralCorridor.enter
execute -- but I never get to the latter, despite apparently successfully instantiating CentralCorridor
.
I'm baffled. Why isn't a_map.this_scene
visible anywhere but within Map.__init__
?
Upvotes: 0
Views: 1911
Reputation: 1123560
this_scene
is only ever a local name in Map.__init__
:
def __init__(self, start_scene):
scenes = {
'central corridor': CentralCorridor,
}
this_scene = scenes[start_scene]()
print this_scene
You need to assign it to an attribute on self
:
def __init__(self, start_scene):
scenes = {
'central corridor': CentralCorridor,
}
self.this_scene = scenes[start_scene]()
Upvotes: 4