Problem with objects copying each other in memory

Chris Rebert clp2 at rebertia.com
Thu Feb 12 17:10:29 EST 2009


On Thu, Feb 12, 2009 at 1:57 PM, dlocpuwons <cameron.pulsford at gmail.com> wrote:
> Using Python 2.6.1...
>
> I am (attempting) to make an A* search for a chess problem, but I am
> running into a really annoying shared memory issue in my successor
> function. Here it is stripped down to the important parts that relate
> to my problem.
>
> def successors(self):
>                result = []
>                moves = [[2, 1], [2, -1], [-2, 1], [-2, -1], [1, 2], [1, -2], [-1,
> 2], [-1, -2]] #possible moves for a knight
>
>                for i in moves:
>                        temp = Knight(self.x, self.y, self.g, self.h, self.gp, self.sl)
>                        temp.x += i[0]
>                        temp.y += i[1]
>                        temp.sl.append([temp.x, temp.y]) #Adds the new current state to the
> visited states list
>                        result.append(temp)
>                return result
>
> The method creates a temporary Knight object, increments it to the new
> position and then adds this new position to its list of visited
> states. Then it returns a list of these 8 new objects. The problem
> seems to be with the "result.sl.append()" line. As the method chugs
> along and creates the new objects the "temp.sl" lines seems to stay in
> memory, so when the method is done all the new objects have all the
> new states that were made over the course of the method instead of
> just their own created in the loop. For example when I try to get
> successors for a piece that is initially at (2,2) with no previously
> visited states, the method prints this out for the sl (state list)
> value

Just a guess based on the behavior you described, but do you by chance
have the Knight class defined as something like this?:

class Knight(whatever):
    sl = []

If so, that is not the proper way to create an instance variable in
Python. You've instead created a class variable, which is shared by
all instances of the class.

class Knight(whatever):
    def __init__(self, some, args, here):
        self.sl = []

If not, do you by chance define Knight as:

class Knight(whatever):
    def __init__(self, some, args, here, sl=[]):
        self.sl = sl

If so, you've fallen victim to the Important Warning on
http://docs.python.org/tutorial/controlflow.html#default-argument-values
under "Default Argument Values". The correct way to code it is:

class Knight(whatever):
    def __init__(self, some, args, here, sl=None):
        if sl is None: sl = []
        self.sl = sl

Cheers,
Chris

-- 
Follow the path of the Iguana...
http://rebertia.com



More information about the Python-list mailing list