"self" as method attribute
Question: 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


Answer: 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`).

