我的目标是创建一个包含多个列表的列表,其中每个列表都代表一个游览路线。然而,我遇到一个问题,在代码循环结束后,列表 tours 并不是一个包含多个不同、随机排列的游览路线的列表,而是包含了最后添加到列表中的游览路线。我想这与 Python 的对象引用有关,但我不知道该如何修改代码。我已经尝试使用 del tour,但没有效果。
代码如下:
def initialisePopulation(self, cities):
tours = []
for i in xrange(0, PopulationSize):
tour = Tour(cities)
shuffle(tour.tour)
tours.append(tour)
print str(tour.tour[0].id) + "," + str(tour.tour[1].id) + "," + str(tour.tour[2].id) + "," + str(tour.tour[3].id) + "," + str(tour.tour[4].id)
del(tour)
print "-"
for j in xrange(0, PopulationSize):
print str(tours[j].tour[0].id) + "," + str(tours[j].tour[1].id) + "," + str(tours[j].tour[2].id) + "," + str(tours[j].tour[3].id) + "," + str(tours[j].tour[4].id)
当我打印每个游览路线时,一切都很正常。但是,当我打印 tours 的内容时,每个项目都是相同的。
输出如下:
2,3,1,5,4
2,4,3,1,5
2,3,4,1,5
4,3,1,5,2
3,4,1,5,2
-
3,4,1,5,2
3,4,1,5,2
3,4,1,5,2
3,4,1,5,2
3,4,1,5,2
Tour 类:
class Tour(object):
'''
classdocs
'''
def __init__(self, cityList):
self.tour = cityList
self.size = len(cityList)
self.fitness = self.getFitness(self.tour)
def getFitness(self, tour):
fitness = sum([self.euclideanDistance(tour[i], tour[i+1]) for i in xrange(0, self.size-1)])
return fitness
def euclideanDistance(self, p, q):
distance = sqrt((p.x - q.x)**2 + (p.y - q.y)**2)
return distance
2. 解决方案
答案 1:
有两种可能性导致了这个问题,但从你没有展示的代码中无法确定。
第一种可能性: 你将 tour 存储为 Tours 中的类属性而不是实例属性,因此它们共享相同的属性:
class Tour(object):
tour = something
第二种可能性: 你将城市列表复制到 tour 实例属性中,因此它们具有不同的属性,但所有属性都引用同一个列表值:
class Tour(object):
def __init__(self, cities):
self.tour = cities
从你更新的问题来看,是第二种情况。
从根本上说,这与常见问题解答中的多维列表问题相同,只是这里不是直接有一个列表的列表,而是有一个包含列表的对象的列表。
无论哪种情况,你想让 Tour 中的每个对象有独立的列表,以便可以使用 shuffle 等函数对它们进行单独修改,对吧?那么你需要显式地复制列表。例如:
class Tour(object):
def __init__(self, cities):
self.tour = cities[:]
但是,我可能会对这段代码进行不同的编写。首先,创建一个不会执行就地修改的 shuffled 方法,而是返回一个新列表:
def shuffled(iterable):
result = list(iterable)
shuffle(result)
return result
然后,你可以用这个方法替换整个第一个循环:
tours = [Tour(shuffled(cities)) for _ in xrange(PopulationSize)]
同时,你可以将第二个循环替换为:
for tour in tours:
print ','.join(city.id for city in tour)
for tour in tours 这部分解释了 for 循环教程。第二行使用解析和 join 方法,可以避免重复五次。