BETA

Pythonのリストで参照渡しでないコピーを作成する話

投稿日:2018-11-12
最終更新:2018-11-12
※この記事は外部サイト(https://qiita.com/hrs1985/items/4e7bba39a3...)からのクロス投稿です

なんということもない話なのですが、 これで困ったことがなかったので改めて勉強しなおしたという話です。 今更ではありますが、pythonでは何かを代入すると値ではなく参照が渡されます。

a = 1
b = a
print(id(a))
print(id(b))

>1928654608
>1928654608

整数型の場合、bに別の値を代入するとbのみ新しいアドレスに参照先が切り替わります。 元のaについては変更を行いません。

b = 334
print(a)
print(b)

>1
>334

しかし、リストの場合は勝手が違っています。

a = [1, 2, 3, 4]
b = a
print(a)
print(b)

>[1, 2, 3, 4]
>[1, 2, 3, 4]

b.pop(1)
print(a)
print(b)

>[1, 3, 4]
>[1, 3, 4]

bにリストaを代入し、popでbから要素を削除すると直接変更していないaの内容も変わっています。 参照先もそのままです。

print(id(a))
print(id(b))

>2277581359240
>2277581359240

「aの元の情報を保持したままbに破壊的な操作を加えたい」みたいな場合には以下のように、 スライスを使ってコピーを生成するのが手軽です。

a_ =[1, 2, 3, 4]
c = a_[:]
c.pop(1)
print(a_)
print(c)

>[1, 2, 3, 4]
>[1, 3, 4]

(2016/7/27追記)list()とかcopyモジュールを使ってもできるという意見をもらったので試しました。

a = [1, 2, 3, 4]
b = list(a)
b.pop(1)
print(a)
print(b)

>[1, 2, 3, 4]
>[1, 3, 4]

import copy
a = [1, 2, 3, 4]
c = copy.copy(a)
c.pop(1)
print(a)
print(c)

>[1, 2, 3, 4]
>[1, 3, 4]

やったぜ。

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@kiyoの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!