2013-12-21 5 views
1

다음 코드에서 채울 목록이 있습니다. 채우면 다시 액세스하지만 목록이 재설정됩니다.python의 인스턴스 변수가 재설정됩니다.

왜 이런 일이 발생합니까? 당신이 볼 수 있듯이

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 

은, 모든 값은 그 숫자가 어디에서 온 "82.7160188343", 심지어 를 모르는 재설정 얻을 : 여기

#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)]) 

이 출력됩니다.

아이디어가 있으십니까?

감사합니다.

답변

3

같은 값을 공유하는 모든 값을 만듭니다. 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) 

... 모든 Value(pointsList) 같은 pointsList로 새 Value 오브젝트를 구축합니다. 그들은 모두 똑같이 목록을 참조 결국, 그래서

self.pointsList = pointsList 

: Value.__init__ 내부, 그것은 그 목록을 복사하지 않습니다, 그냥이한다. Value.__init__ (예컨대, self.pointsList = pointsList[:]) 내부의 목록을

  • 복사 :


    당신은 아마 다음 세 가지 중 하나를 수행합니다.

  • 복사본을 에서Value.__init__ (예 : org = Value(pointsList[:]))으로 전달하십시오.
  • 루프를 반복 할 때마다 동일한 목록을 반복적으로 사용하는 대신 새 목록을 새로 만듭니다.

제 3의 경우는 사용 사례에서 가장 깨끗하다고 ​​생각합니다. 이 작업을 수행 할 수 있도록 ...

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

:

내가 새로운 단행 사본을 반환하는 shuffled 함수를 작성할 것

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) 
+1

멋진 아, 그래서 기본적으로 내 인스턴스 변수를 나는 "인스턴스화 할 때 값 "은 모두 같은 목록을 가리키며 끝났습니다. 변수"self.pointsList "를 설정할 때 모두 메모리의 동일한 위치를 가리키기 때문입니다. 나는 다음에 그것을 조심할 것이다, 좋은 붙잡음! – yonatano

+0

@ Yoni201 : 정확합니다. 당신이 확실하지 않을 때마다 항상'is' 연산자 나'id' ​​함수를 사용하여 다음을 검사 할 수 있습니다 : if self.values ​​[0] .pointsList is self.values ​​[1].pointsList'는 사실입니다, 당신은 어딘가 망쳤습니다. 그러나 한 곳에서 돌연변이를 일으키지 않고 새로운 목록을 만들 수 있다면 문제가 발생하지 않는다는 것을 의미하기 때문에 종종 할 가치가 있습니다. – abarnert