Понимание списка возвращает только последнюю итерацию

Я пытаюсь создать совокупность матриц смежности с разными случайными весами, для которых я использую приведенный ниже код. Однако моя проблема заключается в том, что после запуска все веса соответствуют последней итерации понимания списка? При печати этих adjacencylists во время генерации все работает нормально, однако вывод функции getPopulation в 5 раз превышает тот же набор параметров.

Кажется, что это было бы легко исправить, но чего-то (я думаю, возможно, очень простого) не хватает. Может быть, проблема, когда требуется глубокая копия или что-то в этом роде?

Уже пробовал использовать обычные циклы for, операторы печати и т.д.

import networkx as nx
import numpy as np

G = nx.DiGraph()
G.add_nodes_from(["Sadness", "Avoidance", "Guilt"])
G.add_edges_from([("Sadness", "Avoidance")], weight=1)
G.add_edges_from([("Avoidance", "Sadness")], weight=1)
G.add_edges_from([("Avoidance", "Guilt"), ("Guilt", "Sadness")], weight=1)
parameters = nx.to_numpy_matrix(G)

def getRandParamValue(adj):
    for p in np.transpose(adj.nonzero()):
        adj[p[0], p[1]] = adj[p[0], p[1]] * np.random.uniform()
    print(adj)
    return adj

def getPopulation(size, initParam):
    return [getRandParamValue(initParam) for i in range(size)]

getPopulation(5, parameters)

После печати вывода в функции getRandParamValue все работает нормально:

[[0.         0.40218464 0.        ]
 [0.07330473 0.         0.7196376 ]
 [0.53148413 0.         0.        ]]
[[0.         0.34256617 0.        ]
 [0.01773899 0.         0.12460768]
 [0.1401687  0.         0.        ]]
[[0.         0.11086942 0.        ]
 [0.01449088 0.         0.04592752]
 [0.07903259 0.         0.        ]]
[[0.         0.01970867 0.        ]
 [0.00589168 0.         0.00860802]
 [0.06942081 0.         0.        ]]
[[0.         0.01045412 0.        ]
 [0.00084878 0.         0.00713334]
 [0.0024654  0.         0.        ]]

Однако вывод getPopulation не идентичен предыдущему выводу, хотя этого и следовало ожидать:

[matrix([[0.        , 0.01045412, 0.        ],
         [0.00084878, 0.        , 0.00713334],
         [0.0024654 , 0.        , 0.        ]]),
 matrix([[0.        , 0.01045412, 0.        ],
         [0.00084878, 0.        , 0.00713334],
         [0.0024654 , 0.        , 0.        ]]),
 matrix([[0.        , 0.01045412, 0.        ],
         [0.00084878, 0.        , 0.00713334],
         [0.0024654 , 0.        , 0.        ]]),
 matrix([[0.        , 0.01045412, 0.        ],
         [0.00084878, 0.        , 0.00713334],
         [0.0024654 , 0.        , 0.        ]]),
 matrix([[0.        , 0.01045412, 0.        ],
         [0.00084878, 0.        , 0.00713334],
         [0.0024654 , 0.        , 0.        ]])]

Матрица параметров выглядит следующим образом:

[[0. 1. 0.]
 [1. 0. 1.]
 [1. 0. 0.]]

если вы хотите, чтобы в вашем списке был тот же результат, что и напечатанный, просто добавьте .copy() в return из getRandParamValue, например return adj.copy()

Ben.T 30.05.2019 18:53

Потрясающий! Спасибо большое, а зачем это нужно?

Bas Chatel 30.05.2019 18:55

Возможный дубликат Как клонировать или скопировать список?

Devesh Kumar Singh 30.05.2019 18:57

@BasChatel это потому, что массивы numpy являются изменяемыми, не уверен, что могу дать больше объяснений, возможно, прочитайте это (не в stackoverflow), это может помочь вам лучше понять.

Ben.T 30.05.2019 19:08

Я хочу добавить комментарий к тому, что вы делаете, если вы определяете size большим числом, все значение будет стремиться к 0, так как каждый раз, когда вы умножаете предыдущее значение на значение от 0 до 1, посмотрите сами с печатью последний элемент списка из 100 элементов: print (getPopulation(100, parameters)[-1]). Просто чтобы быть уверенным, что вы сейчас, что произойдет

Ben.T 30.05.2019 19:21
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
5
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Итак, проблема в следующем:

def myfunction(L):
    L[0] += 1
    return L

my_outer_list = [1,2,3]
newlist = myfunction(my_outer_list)

print(newlist)
> [2, 2, 3]
print(my_outer_list)
> [2, 2, 3]

newlist[2]=-1
print(newlist)
> [2, 2, -1]
print(my_outer_list)
> [2, 2, -1]

Я передал объект my_outer_list в функцию. Затем этот объект модифицируется, и объект возвращается. Так что теперь newlist и my_outer_list не просто равны, это два разных названия одного и того же. То, что я делаю с этим объектом, изменяет объект, и вы видите эти изменения независимо от того, какое имя вы используете.

Вот что случилось с тобой. Если бы вместо этого у меня было myfunction return L.copy(), он вернул бы копию L, а не точно L.

Так что вам стоит вернуться adj.copy().

Спасибо за ваше объяснение! Вы все мне очень помогли :)

Bas Chatel 31.05.2019 09:26

Другие вопросы по теме