Reputation: 709
I am attempting to teach myself Python at the moment and I am trying to work my way through a python program, which is essentially a pacman game. Whilst doing so, I discovered the following class call which contains 'self' as a method attribute.
game = Game(agents, display, self, catchExceptions=catchExceptions)
THE CONTEXT:
This method call is part of the following function:
class ClassicGameRules:
"""
These game rules manage the control flow of a game, deciding when
and how the game starts and ends.
"""
def __init__(self, timeout=30):
self.timeout = timeout
def newGame( self, layout, pacmanAgent, ghostAgents, display, quiet = False, catchExceptions=False):
[1] agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()]
[2] initState = GameState()
[3] initState.initialize( layout, len(ghostAgents) )
[4] game = Game(agents, display, self, catchExceptions=catchExceptions)
[5] game.state = initState
[6] self.initialState = initState.deepCopy()
[1] Just to make this a little more palatable, 'agents' contain the pacman and ghost agent objects combined into a list of lists, which when printed looks something like this:
[<keyboardAgents.KeyboardAgent instance at 0x1004fe758>, <ghostAgents.RandomGhost instance at 0x1004fe518>, <ghostAgents.RandomGhost instance at 0x1004fe7a0>, <ghostAgents.RandomGhost instance at 0x1004fe950>, <ghostAgents.RandomGhost instance at 0x1004feb90>]
[2] initState = GameState(): GameState() is a data object containing all sorts of information about the Game state
[3] initState.initialize( layout, len(ghostAgents) ): initialises the very first game state from a layout array. This layout array lets the program know where the pacman and ghosts spawn, where the food and capsules are displayed and where walls can be found.
[4] game = Game(agents, display, self, catchExceptions=catchExceptions): The Game class manages the control flow, soliciting actions from agents. Agents can be a keyboard agent (controlled by the player, who controls the pacman) and automated agents controlling the ghosts (see [1]).
[5] game.state = initState: copies the content of [2] into the variable game.state.
[6] self.initialState = initState.deepCopy(): deepCopy is a function which runs a copy operation on variables which define the game state of the game board, such as the layout or the position of the food.
CLASS GAME: Here is the code of the class Game:
class Game:
"""
The Game manages the control flow, soliciting actions from agents.
"""
def __init__( self, agents, display, rules, startingIndex=0, muteAgents=False, catchExceptions=False ):
self.agentCrashed = False
self.agents = agents ## agents contain the pacman and ghost agent objects combigned into a list of lists agents = [pacmanAgent] + ghostAgents[:layout.getNumGhosts()]
self.display = display
#print("This is the display object" + str(self.display))
self.rules = rules ## The rules are passed on as the self attribute of the ClassicGameRules class within the call of Game in newGame [REF 115].
self.startingIndex = startingIndex ## starting index is given as default attribute by the __init__ method.
self.gameOver = False
self.muteAgents = muteAgents
self.catchExceptions = catchExceptions
self.moveHistory = []
self.totalAgentTimes = [0 for agent in agents] ## This creates a list that replaces the list elements of the agents list, which contains the agent objects, with zeros. It looks something like this [0,0,0]
##print(self.totalAgentTimes)
self.totalAgentTimeWarnings = [0 for agent in agents]
self.agentTimeout = False
import cStringIO
self.agentOutput = [cStringIO.StringIO() for agent in agents]
WHAT CONFUSES ME
When game = Game(agents, display, self, catchExceptions=catchExceptions) is called, "self' is passed on to Game as an attribute. In Game the data contained within "self" takes is placed within the "rules" variable.
But does does this variable contain?
Intuitively I would suggest that it would be the "self" instance of the newGame object. But seeing how this method is called self.initialState = initState.deepCopy(), which doesn't seem to make sense...
Or are we referencing the self - object of the ClassicGameRules class?
I know this was a handful of text to read, but I wasn't quite sure how to shorten this question. Please let me know if more information is required. Any help would be highly appreciated. :)
Z_101
Upvotes: 0
Views: 306
Reputation: 121974
The line:
game = Game(agents, display, self, catchExceptions=catchExceptions)
in ClassicGameRules.newGame
calls Game.__init__
with three positional arguments and one keyword argument, plus the implicit first positional argument of the new Game
instance. Game.__init__
is defined as:
def __init__(self, agents, display, rules, startingIndex=0, muteAgents=False, catchExceptions=False ):
# agents display self [default] [default] catchExceptions
Crucially, the self
in the calling function is not the same as the self
in the called function. This call passes the ClassicGameRules
instance as the argument rules
to the Game
instance. This creates a two-way link:
Game
instance within ClassicGameRules
instance methods via self.game
; andClassicGameRules
instance within Game
instance methods via self.rules
.The next part:
game.state = initState
self.initialState = initState.deepCopy()
sets the state
attribute of the Game
instance to initState
, but then saves a copy of that state to self.initialState
(where self
refers to the ClassicGameRules
instance, as we're inside a ClassicGameRules
instance method).
Upvotes: 1
Reputation: 36141
In the method newGame
of the class ClassicGameRules
, self
represents the current instance of the class:
game = Game( agents, display, self, ...)
v v v
def __init__(self, agents, display, rules, ...)
The first self
of the __init__
method here is to represents to the new object that will be created in the Game
class.
In your case, the Game
class has in rules
a reference to the instance of ClassicGameRules
which called the constructor of the Game
instance. The deepCopy
after has nothing to do and is just to synchronized the initial state of both objects, by coping the state of the object just created (game
) into the "parent" object (instance of ClassicGameRules
).
Upvotes: 1