Pregunta

In the following code, I have a list that I populate. After I populate it, I access it again, but the list gets reset.

Why is this happening?

#Yonatan Oren 12/20/2013
#NIFTY GA Problem
from random import shuffle, randint, randrange

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getX(self):
        return self.x

    def getY(self):
        return self.y

    def getDistance(self, point):
        distance = (((point.getX() - self.x) ** 2) + ((point.getY() - self.y) ** 2)) ** (0.5)
        return distance

class Value:
    def __init__(self, pointsList):
        self.pointsList = pointsList
        self.fitness = 0

    def getFitness(self):
        #add up all of the distances
        fitness = sum([a.getDistance(b) for a,b in zip(*[self.pointsList[i:] for i in range(2)])])
        return fitness

    def getPointsList(self):
        return self.pointsList

    def __lt__(self, other):
        return self.getFitness() < other.getFitness()



class Environment:

    def __init__(self):
        self.values = []

    def createNewEnvironment(self, pointsList): 
        self.pointsList = pointsList

        #create 10 new organisms
        for i in range(10):
            org = Value(pointsList)
            print org.getFitness()
            self.values.append(org)
            shuffle(pointsList)

        for o in self.values:
            print "point_listed: %s" % o.getFitness()


env = Environment()
env.createNewEnvironment([Point(0,0), Point(5,0), Point(10,0), Point(10,5), Point(10,10), Point(5,10), Point(0, 10), Point(0, 5), Point(0,0)])

Here is the output:

40.0
75.3224755112
76.7924273619
56.1803398875
67.6831552862
84.7542230981
79.7542230981
57.3935433231
75.6120874744
70.6120874744
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343
point_listed: 82.7160188343

As you can see, all of the values get reset to "82.7160188343", I don't even know where that number came from.

Any ideas?

Thanks.

¿Fue útil?

Solución

You're creating a whole bunch of values that all share the same pointsList.

It's not that their instance variables are being reset, it's that all of those variables are names for the exact same value, so when you change that value, they all see it.


In this code:

self.pointsList = pointsList

#create 10 new organisms
for i in range(10):
    org = Value(pointsList)
    print org.getFitness()
    self.values.append(org)
    shuffle(pointsList)

… every Value(pointsList) constructs a new Value object with the same pointsList. Inside Value.__init__, it doesn't copy that list, it just does this:

    self.pointsList = pointsList

So, they all end up just referring to the same list.


You probably want to do one of three things:

  • Copy the list inside Value.__init__ (e.g., self.pointsList = pointsList[:]).
  • Pass a copy to Value.__init__ (e.g., org = Value(pointsList[:])).
  • Create a new list each time through the loop instead of reusing the same one over and over.

I think the third one of these is cleanest in your use case.

I'd write a shuffled function that returns a new shuffled copy:

def shuffled(seq):
    retval = list(seq)
    shuffle(retval)
    return retval

… so you can do this:

self.pointsList = pointsList

#create 10 new organisms
for i in range(10):
    pointsList = shuffled(pointsList)
    org = Value(pointsList)
    print org.getFitness()
    self.values.append(org)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top