Python リストの深いコピーと浅いコピー

目次

概要

= コピー

リスト関数 copy() コピー

[:]コピー

リスト構造の変更のデモンストレーション

ディープコピー関数

浅いコピーと深いコピーとは何ですか、また 2 つの違いは何ですか

要約する


概要

Pythonのリストはコピーできますが、浅いコピーと深いコピーがあり、深いコピーと浅いコピーが何なのかわからない人もいると思うので、今日はそれについて話しましょう。

= コピー

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: [email protected]

list1 = ["A", "B"]

list2 = list1

print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

list2 に要素を追加し、操作の結果を確認すると、両方のリストが変更されていることがわかります。したがって、= 記号はリストの最も単純なコピーですが、2 つのリストの ID が同じであることがわかるため、コピーとしてカウントすることはできません。

リスト関数 copy() コピー

コピー方法を変えてみよう

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: [email protected]

list1 = ["A", "B"]

list2 = list1.copy()

print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

ID が異なるため、実際にコピーがコピーされるのはここです。実行結果を見ると、list2 のみが変更されていますが、浅いコピーであることがわかります。

[:]コピー

別のコピー方法を見てみましょう。実際、厳密に言えば、スライスはコピーではなく、リストがスライスされた後は新しいリストが返され、元のリストは変更されません。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: [email protected]

list1 = ["A", "B"]

list2 = list1[:]

print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
list2.append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

結果は上記と同じです

上記では 3 つの例を示していますが、浅いコピーに属するのは 2 番目のコピー方法だけです。

リスト構造の変更のデモンストレーション

ここでは引き続きコピー関数を使用します。この関数は [:] を使用するのと同じです。以下の 2 つの変更があります。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: [email protected]

# 在列表中添加一个列表元素
list1 = ["A", "B", [1, 2]]

list2 = list1[:]

print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
# 这里我们修改列表中的列表,对内层列表进行修改
list2[2].append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

実行結果を見ると、内部リストが変更されていることがわかります。あなたはそれを正しく読んでいます。引き続き下を見てください。

では、このネストされたリストのシナリオで、実際に独立してコピーされ、相互に干渉しない場合はどうなるでしょうか? これはディープコピーを使用します。

ディープコピー関数

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author: rex.cheny
# E-mail: [email protected]

# 导入该模块
import copy

# 在列表中添加一个列表元素
list1 = ["A", "B", [1, 2]]

# 深复制
list2 = copy.deepcopy(list1)

print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))
# 这里我们修改列表中的列表,对内层列表进行修改
list2[2].append("C")
print("list1: ", list1, "ID: ", id(list1))
print("list2: ", list2, "ID: ", id(list2))

予想どおりの実行結果を確認します。

浅いコピーと深いコピーとは何ですか、また 2 つの違いは何ですか

実際、効果の観点からは、この 2 つの違いを理解する必要がありますが、この問題について説明したい場合は、データ型について説明する必要があります。データ型には次の 2 種類があります。

  • 文字列、数値、ブール値などの基本的なデータ型。保存されるのは実際のデータです。
  • オブジェクト データ型 (参照データ型) は、オブジェクトへの参照を格納するクラスのインスタンスであるオブジェクトです。

代入ステートメント = は何を意味しますか? たとえば、name = "tom" 代入ステートメント (=) は変数名をメモリ オブジェクトにバインドします。オブジェクトが存在する場合は直接バインドされ、存在しない場合は最初に作成されてバインドされます。名前には「tom」へのポインタが格納され、tom を格納するメモリ領域には tom の実データが格納されます; list1 = [1, 2] この種の list1 はリスト オブジェクトのポインタを格納しますが、リスト オブジェクト自体は格納しませんデータは他のオブジェクトへの参照です。ここでのリストには 2 つのオブジェクト 1 と 2 が含まれています。これら 2 つのオブジェクトは実際にはメモリ内に存在します。リスト オブジェクトはこれらのオブジェクトを参照するだけであり、リストは単なるデータの編成です。フォーム。

浅いコピー: 指すポインターをコピーします。データはメモリー内に 1 つのコピーだけですが、コピーされるオブジェクトのレベルは 1 つだけです。別の参照データ型がある場合は機能しません。

深いコピー: 再帰的な浅いコピーとして理解できます。

それでもわからない場合は、下の写真を見てください

次の図はディープコピーを使用した後の図です

要約する

互いに干渉しない 2 つのリストを生成したい場合は deepcopy を使用し、それ以外の場合は選択できます。

おすすめ

転載: blog.csdn.net/weixin_47649808/article/details/126388458