JSのオブジェクトが参照渡しであることに知らずにハマったあと、Pythonでも参照渡しでループを回してlistの要素が全て同じ、みたいな事例に出くわしたので整理のために書いておく。
JSでハマったコード
mapDataをLeftとRightとで別に持ちたかったが、GETするたびにresultが更新される → 参照渡しなので、LeftもRightも同じになってしまっていた。
// 以下、ajaxでGETしたときのコールバック
svg = _setSvgArea( id );
if ( id == "#mapLeft" ) {
// 1. _getJapanMapがオブジェクトを返す。
mapDataLeft = _getJapanMap( result, JAPAN_MAP );
} else if ( id == "#mapRight" ) {
// 2. もう一回GETすると、resultが更新されるとmapDataLeftも更新されてしまう。
mapDataRight = _getJapanMap( result, JAPAN_MAP );
};
jQueryの$.extendで解決。
mapDataLeft = $.extend(true, {}, _getJapanMap( result, JAPAN_MAP ) );
pythonで出くわしたコード
この場合はループの中のcolumn
が参照渡し先。medicine['medicine_name']
などで値を更新すると、前のループでappend
したcolumn
まで更新されてしまう。
for medicine in medicines:
column = GET_MEDICINES_MESSAGE['column']
column['text'] = medicine['medicine_name']
columns.append(column)
copyモジュールのdeepcopyで解決。
from copy import deepcopy
.
.
for medicine in medicines:
column = GET_MEDICINES_MESSAGE['column']
column['text'] = medicine['medicine_name']
columns.append(deepcopy(column))
結局は、どういうときにディープコピーが必要になるのか?
変数や関数でつくったオブジェクト(辞書)をループで回すなど繰り返し処理するときにディープコピーを使う。
変数や関数でつくったオブジェクト(辞書)をループで回すなど繰り返しで値を代入するときにディープコピーを使う。