Эти два кода должны делать то же самое, но первый не работает, как я ожидаю - PullRequest
0 голосов
/ 06 сентября 2018

Python

Пожалуйста, объясните, почему эти два кода работают по-разному. На самом деле я пытаюсь создать вид ИИ, в котором в начальных поколениях люди будут двигаться в случайных направлениях.Для простоты кода я предоставил несколько случайных направлений в Мозге себе.

Существует класс Individual , который дает мозгиндивидуальный.У него также есть функция, которая возвращает ребенка с ТОЧНО таким же мозгом (то же самое направление, в котором он должен идти) с родителем.

У меня есть два кода:

Первый: Когда в родительском объекте изменяются некоторые направления, то же самое изменяется и в дочернем элементе (или если изменяется в дочернем элементе, он также изменяется в родительском), чего я не хочу, чтобы это произошло.

Второй: Этот не полностью мой (и поэтому я не знаю, почему он работает), но он работает нормально.Некоторое направление, измененное в родителе, не изменяется у ребенка, и наоборот.

Пожалуйста, кто-нибудь объяснит мне разницу и почему первый не сработал.Буду очень признателен за ваш ответ.


Первый:

class Brain():
    def __init__(self):
        self.directions = [[1, 2], [5, 3], [7, 4], [1, 5]]

class Individual():
    def __init__(self):
        self.brain = Brain()

    def getChild(self):
        child = Individual()
        child.brain = self.brain
        return child

parent = Individual()
child = parent.getChild()

parent.brain.directions[0] = [5, 2]

print(parent.brain.directions)
print(child.brain.directions)

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

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



Второй:

class Brain():
    def __init__(self):
        self.directions = [[1, 2], [5, 3], [7, 4], [1, 5]]

    def clone(self):
        clone = Brain()
        for i, j in enumerate(self.directions):
            clone.directions[i] = j
        return clone

class Individual():
    def __init__(self):
        self.brain = Brain()

    def getChild(self):
        child = Individual()
        child.brain = self.brain.clone()
        return child

parent = Individual()
child = parent.getChild()

parent.brain.directions[0] = [5, 2]

print(parent.brain.directions)
print(child.brain.directions)

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

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

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

В первом случае вы ссылаетесь на один и тот же объект. Попробуйте добавить следующий оператор печати в первом случае.

print (id(parent.brain))
print (id(child.brain))

В первом случае добавлена ​​новая ссылка для Brain (). Вы можете видеть, как он справляется.

class Brain():
    def __init__(self):
        self.directions = [[1, 2], [5, 3], [7, 4], [1, 5]]

class Individual():
    def __init__(self):
        self.brain = Brain()

    def getChild(self):
        child = Individual()
        child.brain = Brain()
        return child

parent = Individual()
child = parent.getChild()

parent.brain.directions[0] = [5, 2]

print(parent.brain.directions)
print(child.brain.directions)
0 голосов
/ 06 сентября 2018

В первом коде установка child.brain = self.brain не делает то, что вы ожидаете. Это мелкая копия, означающая, что она просто создает новый указатель на тот же экземпляр Brain(). Так что теперь child.brain и self.brain указывают на один и тот же Brain() в памяти.

Во втором коде вы делаете глубокую копию. Таким образом, вы фактически выделяете еще Brain() в памяти. Теперь child.brain и parent.brain указывают на их собственный отдельный экземпляр Brain() в памяти.

...