为什么添加新列表后数组中的所有列表都会更改?

时间:2019-03-05 03:35:41

标签: python python-3.x

我正在使用python 3.6进行编码,并且正在研究遗传算法。生成新填充时,将新值附加到数组时,数组中的所有值都将更改为新值。我的功能有问题吗?

代码:

from fuzzywuzzy import fuzz
import numpy as np
import random
import time

def mutate(parent):
    x = random.randint(0,len(parent)-1)
    parent[x] = random.randint(0,9)
    print(parent)
    return parent

def gen(cur_gen, pop_size, fittest):
    if cur_gen == 1:
        population = []
        for _ in range(pop_size):
            add_to = []
            for _ in range(6):
                add_to.append(random.randint(0,9))
            population.append(add_to)
        return population
    else:
        population = []
        for _ in range(pop_size):
            print('\n')
            population.append(mutate(fittest))
            print(population)
        return population

def get_fittest(population):
    fitness = []
    for x in population:
        fitness.append(fuzz.ratio(x, [9,9,9,9,9,9]))
    fittest = fitness.index(max(fitness))
    fittest_fitness = fitness[fittest]
    fittest = population[fittest]
    return fittest, fittest_fitness

done = False
generation = 1
population = gen(generation, 10, [0,0,0,0,0,0])
print(population)

while not done:
    generation += 1
    time.sleep(0.5)
    print('Current Generation: ',generation)
    print('Fittest: ',get_fittest(population))
    if get_fittest(population)[1] == 100:
        done = True
    population = gen(generation, 10, get_fittest(population)[0])
print('Population: ',population)

输出:

Fittest:  ([7, 4, 2, 7, 8, 9], 72)


[3, 4, 2, 7, 8, 9]
[[3, 4, 2, 7, 8, 9]]


[3, 4, 2, 7, 5, 9]
[[3, 4, 2, 7, 5, 9], [3, 4, 2, 7, 5, 9]]


[3, 4, 2, 7, 4, 9]
[[3, 4, 2, 7, 4, 9], [3, 4, 2, 7, 4, 9], [3, 4, 2, 7, 4, 9]]


[3, 1, 2, 7, 4, 9]
[[3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9]]


[3, 1, 2, 7, 4, 2]
[[3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2]]


[3, 1, 2, 5, 4, 2]
[[3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2]]


[3, 1, 2, 5, 4, 2]
[[3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2]]


[3, 1, 2, 5, 4, 5]
[[3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5]]


[3, 1, 2, 5, 4, 3]
[[3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3]]

2 个答案:

答案 0 :(得分:0)

就在名称中:

def mutate(parent):
    x = random.randint(0,len(parent)-1)
    parent[x] = random.randint(0,9)
    print(parent)
    return parent

mutate并没有创建新的list,而是修改了现有的list,并返回了对传递的相同list的引用。 population.append(mutate(fittest))一次又一次地愉快地为fittest存储别名,并且由于fittest从未被替换,因此它只会不断变异并为其存储新的别名。

如果目标是每次在给定阶段存储list的快照,请对其进行复制,并进行以下更改:

population.append(mutate(fittest))

收件人:

population.append(mutate(fittest)[:])

其中list的完整切片将进行浅表复制。 population.append(mutate(fittest).copy())也可以在现代Python上运行,就像import copy一样,然后执行population.append(copy.copy(mutate(fittest)))或(如果内容本身是可变的,尽管在这种情况下它们不是可变的){{1} }。

请注意,通常来说,Python函数实际上不应该同时对进行突变,并且会返回突变后的值,因为这样会引起混淆。

打算在适当位置进行突变的Python代码会返回population.append(copy.deepcopy(mutate(fittest)))(通常隐式地是根本不返回),因此您要使用的代码实际上是:

None

并用于:

def mutate(parent):
    x = random.randint(0,len(parent)-1)
    parent[x] = random.randint(0,9)
    print(parent)

答案 1 :(得分:0)

您一直将对同一列表的引用if data=='w': 传递到fittest,后者会就地修改列表,并将其附加到mutate,因此在下一次迭代将反映在population列表中对fittest的所有引用中。

您应该将population列表的副本传递给fittest

mutate