基於@ Armin的評論的另一刺。這確實展覽相關deepcopy的行爲:
import random
width = 5
height = 5
class Brain(object):
def __init__(self):
self.w = [[1]]
self.ix = [[1]]
def mutate(self):
self.w[0].append(1)
class Animal(object):
def __init__(self):
self.brain = Brain()
self.x = random.randint(0, width)
self.y = random.randint(0, height)
self.age = 0
self.fitness = 10
def reproduce(parent):
child = Animal()
child.brain.w= parent.brain.w[:]
child.brain.ix= parent.brain.ix[:]
child.x,child.y = random.randint(0,width),random.randint(0,height)
child.age = 0
child.fitness= 9 + parent.fitness/10 #parent.fitness/2
mutation = random.choice([0,1,1,1,1,1,1,1,1,2,3,4,5])
for b in range(mutation):
child.brain.mutate()
animals.append(child)
animals = []
parent = Animal()
animals.append(parent)
print parent.brain.w
#reproduce(parent)
import copy
reproduce(copy.deepcopy(parent))
for each in animals:
print each.brain.w
這裏的解決辦法是沒有存儲在你的對象之間複製一個可變型的狀態值;在這種情況下是一個列表,但它可能是任何可變對象。
編輯: 你在做的是在原始代碼是將parent.brain.w
的內容複製到child.brain.w
。 Python具有賦值給原始對象的屬性,而不是對象或內容的副本(除非使用copy
模塊)。 The docs掩蓋了這個井。簡潔,這意味着符合下列條件:
>>> a = [1, 2, 3, 4, 5]
>>> b = a
>>> b.append(6)
>>> b
[1, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
>>> a is b
True
也就是說,兩個a
和b
是相同的列表。這不完全是你在做什麼;你複製一個列表到一個對象,但這是等價的:
>>> a = [[1, 2, 3]]
>>> b = []
>>> b = a[:] # What you are doing
>>> b is a
False
>>> b[0] is a[0]
True
>>> b[0].append(4)
>>> b[0]
[1, 2, 3, 4]
>>> a[0]
[1, 2, 3, 4]
如果你的類型是不可變的,那麼當你修改它,將創建一個新的對象。例如,考慮一個元組(這是不可變的)的一個有點等效的列表:
>>> a = [(1, 2, 3)]
>>> b = []
>>> b = a[:]
>>> b is a
False
>>> b[0] is a[0] # Initially the objects are the same
True
>>> b[0] += (4,) # Now a new object is created and overwrites b[0]
>>> b[0] is a[0]
False
>>> b[0]
(1, 2, 3, 4)
>>> a[0]
(1, 2, 3)
我想你將需要發佈'動物'的代碼。 – 2013-03-02 22:53:23
只是一個猜測,但也許'brain.w'或'brain.ix'是列表的列表?然後'w [:]'給你一個新的列表,其中仍然包含相同的舊子列表。 – 2013-03-02 22:55:56
使用[:]應該製作父腦的副本。你能發佈更多的代碼嗎?就我個人而言,我會重現()一個動物類的方法。 – Alex 2013-03-02 22:57:23