Мне нужна помощь в понимании непреднамеренной зависимости в этом коде - PullRequest
0 голосов
/ 03 января 2019

Я создал этот автономный пример, чтобы изолировать поведение, которое я пытаюсь понять:

from pprint import pprint

TRADES_CLOSED = dict()
TRADES_ACTIVE = {
    '2010-01-08 12:00': [1, 'SHORT', 20000, '2010-01-08 12:00', 92.339],
    '2010-01-28 04:00': [2, 'LONG', 10000, '2010-01-28 04:00', 90.378],
    '2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
    '2010-01-29 04:00': [4, 'LONG', 20000, '2010-01-29 04:00', 90.164]}

TRADES_TEST = {k: TRADES_ACTIVE[k] for k in sorted(TRADES_ACTIVE)[-2:]}

pprint(TRADES_ACTIVE)
pprint(TRADES_TEST)

profit_long = TRADES_ACTIVE.pop([key for key, value in TRADES_TEST.items() if value[1] == "LONG"][0])
profit_long.extend(['2010-02-03 12:00', 91.278, 1464.54])

pprint(TRADES_ACTIVE)
pprint(TRADES_TEST)

TRADES_CLOSED[[key for key, value in TRADES_TEST.items() if value[1] == "LONG"][0]] = profit_long

pprint(TRADES_CLOSED)

Я хочу выполнить некоторые операции с двумя последними записями в словаре TRADES_ACTIVE.Поэтому я создаю новый словарь с именем TRADES_TEST, который содержит только последние две записи из TRADES_ACTIVE.

. Код выдает следующие выходные данные:

{'2010-01-08 12:00': [1, 'SHORT', 20000, '2010-01-08 12:00', 92.339],
 '2010-01-28 04:00': [2, 'LONG', 10000, '2010-01-28 04:00', 90.378],
 '2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
 '2010-01-29 04:00': [4, 'LONG', 20000, '2010-01-29 04:00', 90.164]}
{'2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
 '2010-01-29 04:00': [4, 'LONG', 20000, '2010-01-29 04:00', 90.164]}
{'2010-01-08 12:00': [1, 'SHORT', 20000, '2010-01-08 12:00', 92.339],
 '2010-01-28 04:00': [2, 'LONG', 10000, '2010-01-28 04:00', 90.378],
 '2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824]}
{'2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
 '2010-01-29 04:00': [4,
                      'LONG',
                      20000,
                      '2010-01-29 04:00',
                      90.164,
                      '2010-02-03 12:00',
                      91.278,
                      1464.54]}
{'2010-01-29 04:00': [4,
                      'LONG',
                      20000,
                      '2010-01-29 04:00',
                      90.164,
                      '2010-02-03 12:00',
                      91.278,
                      1464.54]}

profit_long listсоздается путем добавления определенного элемента TRADES_ACTIVE.Как и ожидалось TRADES_ACTIVE один элемент короче.Затем profit_long расширяется тремя новыми значениями и используется как запись в словаре TRADES_CLOSED.

Я не понимаю, почему расширение profit_long влияет и на TRADES_TEST.Я долго следил за этим кодом и не могу понять.Для меня profit_long и TRADES_TEST - совершенно разные сущности.Как это возможно?

1 Ответ

0 голосов
/ 03 января 2019

Ваша зависимость вызвана тем фактом, что ваш код устанавливает набор списков с именем TRADES_ACTIVE, а затем копирует некоторые из этих списков в другой набор списков, называемый TRADES_TEST. Но когда вы присваиваете список другой переменной, это присваивание не делает копию списка; он только копирует ссылку на него . Чтобы увидеть это, после каждого из ваших вызовов pprint() сделайте для k,v in somedict.items(): print (k, id(v)). Это покажет вам идентификатор каждого из ваших списков. Когда я это сделал, это то, что я видел. Сначала код:

print("TRADES ACTIVE 1")
pprint(TRADES_ACTIVE)
print("TRADES ACTIVE 1")
for k,v in TRADES_ACTIVE.items(): print (k, id(v))

print("TRADES TEST 1")
pprint(TRADES_TEST)
print("TRADES TEST 1")
for k,v in TRADES_TEST.items(): print (k, id(v))

и затем вывод:

TRADES ACTIVE 1
{'2010-01-08 12:00': [1, 'SHORT', 20000, '2010-01-08 12:00', 92.339],
 '2010-01-28 04:00': [2, 'LONG', 10000, '2010-01-28 04:00', 90.378],
 '2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
 '2010-01-29 04:00': [4, 'LONG', 20000, '2010-01-29 04:00', 90.164]}
TRADES ACTIVE 1
2010-01-08 12:00 2236442430536
2010-01-28 04:00 2236442430856
2010-01-28 12:00 2236442431048
2010-01-29 04:00 2236442431176
TRADES TEST 1
{'2010-01-28 12:00': [3, 'SHORT', 10000, '2010-01-28 12:00', 89.824],
 '2010-01-29 04:00': [4, 'LONG', 20000, '2010-01-29 04:00', 90.164]}
TRADES TEST 1
2010-01-28 12:00 2236442431048
2010-01-29 04:00 2236442431176

Как видите, совпадающие клавиши в двух словах указывают на один и тот же список. Обратите внимание, что идентификатор 2236442431176 повторяется как значение ключа «2010-01-29 04:00» в обоих списках.

Затем ваш код создает еще одну копию одного из этих списков, которая называется profit_long. Это также относится к тому же списку, который встречается в качестве значения в обоих других словах.

print("PROFIT_LONG")
print (id(profit_long))

PROFIT_LONG
2236442431176

и когда вы изменяете этот список (снова id 2236442431176), тогда изменения видны в двух диктовках, потому что все три переменные ссылаются на один и тот же список.

Чтобы исправить это, когда вы делаете копию объекта списка, копируйте список, а не просто ссылку на него. Итак, вместо

TRADES_TEST = {k: TRADES_ACTIVE[k] for k in sorted(TRADES_ACTIVE)[-2:]}

до

TRADES_TEST = {k: TRADES_ACTIVE[k][:] for k in sorted(TRADES_ACTIVE)[-2:]}
...