BETA

pythonの参照渡しをどうすれば回避できるのか

投稿日:2018-10-16
最終更新:2018-10-24

January 12, 2017
https://pyonk.github.io/blog/posts/python-copy/
の投稿をクロス投稿してみます。


ときたまpythonを書いているとこれって値渡しなんだっけ、参照渡しなんだっけと分からなくなります。 たとえば

hoge = {1:1, 2:2, 3:3}
print id(hoge) # 140418104920496

fuga = hoge
print id(fuga) # 140418104920496

fuga.update({
    4:4
})

print hoge == fuga # True

Pythonistなら常識ですよね。

どうすれば回避できるのか

割と単純です。

hoge = {1:1, 2:2, 3:3}
print id(hoge) # 140418104920496

fuga = hoge.copy()
print id(fuga) # 140418107009728

fuga.update({
    4:4
})

print hoge == fuga # False

print hoge # {1:1, 2:2, 3:3}

print fuga # {1:1, 2:2, 3:3, 4:4}

辞書の浅いコピーを取るにはcopy_dict = dict.copy()が簡単ですね。

ちなみに、リストの場合はcopy_list = original_list[:]でコピーが取れます。

ただこれだと浅いコピーになります。

なので

hoge = {1:{2:2, 3:3}}
print id(hoge) # 140418104920496

fuga = hoge.copy()
print id(fuga) # 140418107009728

fuga[1].update({
    4:4
})

print hoge == fuga # True

print hoge # {1: {2: 2, 3: 3, 4: 4}}

print fuga # {1: {2: 2, 3: 3, 4: 4}}

となってしまいます。

浅いコピーの場合は

  • 元のオブジェクト中に見つかったオブジェクトに対する 参照 を挿入

するようです。

深いコピー

上記の通り、オブジェクトの中のオブジェクトは参照渡しになります。

それを回避するために、copyモジュールをimportして、深いコピーを利用します。

import copy

hoge = {1:{2:2, 3:3}}
print id(hoge) # 140418104920496

fuga = copy.deepcopy(hoge)
print id(fuga) # 140418107009728

fuga[1].update({
    4:4
})

print hoge == fuga # False

print hoge # {1: {2: 2, 3: 3}}

print fuga # {1: {2: 2, 3: 3, 4: 4}}

あら素敵。

結構厄介な場面も多いのできちんと覚えたいものです。

参考

8.17. copy 浅いコピーおよび深いコピー操作 Python 2.6ja2 documentation

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

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

@pyonk'の技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう