Python ノート - 深いコピーと浅いコピー

ディープ コピーとシャロー コピーは、Python でオブジェクトをコピーする 2 つの方法であり、異なる特性と適用可能なシナリオがあります。

  1. 浅拷贝(Shallow Copy):

    • copy()メソッドまたはスライス操作を使用して、浅いコピーを作成します。
    • 浅いコピーでは新しいオブジェクトが作成されますが、オブジェクトの要素 (リスト、辞書など) は元のオブジェクトの要素への参照のままです。つまり、新しいオブジェクトの要素は、オブジェクトと同じメモリ アドレスを共有します。元のオブジェクトの要素。
    • 新しいオブジェクト内の要素を変更すると、元のオブジェクト内の対応する要素に影響し、その逆も同様です。
    • 単純なデータ構造や、データの一部を共有する必要があるシナリオに適しています。
  2. ディープコピー:

    • deepcopy()関数を使用して、copyモジュール内にあるディープ コピーを作成します。
    • ディープ コピーは、新しいオブジェクトを作成し、ネストされたリスト、辞書などを含むオブジェクトのすべての要素を再帰的にコピーします。各要素は独立しており、元のオブジェクトとメモリ アドレスを共有しません。
    • 新しいオブジェクトの要素を変更しても、元のオブジェクトの要素には影響しません。逆も同様です。
    • 完全に独立したレプリケーションを必要とする複雑なデータ構造またはシナリオに適しています。

サンプルコード:

import copy

# 原始列表
original_list = [1, [2, 3], [4, 5, 6]]

# 浅拷贝
shallow_copy_list = original_list.copy()  # 或者 shallow_copy_list = original_list[:]
shallow_copy_list[0] = 100
shallow_copy_list[1][0] = 200

# 深拷贝
deep_copy_list = copy.deepcopy(original_list)
deep_copy_list[0] = 1000
deep_copy_list[1][0] = 2000

print("原始列表:", original_list)      # 原始列表: [1, [2000, 3], [4, 5, 6]]
print("浅拷贝列表:", shallow_copy_list)  # 浅拷贝列表: [100, [200, 3], [4, 5, 6]]
print("深拷贝列表:", deep_copy_list)    # 深拷贝列表: [1000, [2000, 3], [4, 5, 6]]

浅いコピーでは、新しいリストのサブリストが変更され、元のリストも影響を受けます。ディープ コピーでは、新しいリストを変更しても元のリストには影響しません。特定のニーズに応じて、適切なコピー方法を選択すると、オブジェクトのコピーおよび変更操作をより適切に処理できます。

特徴 ディープコピー 浅いコピー
コンテンツをコピーする ターゲット オブジェクトの完全に独立したコピーを作成します ターゲット オブジェクトの浅いコピーを作成し、メモリ アドレスの一部を共有します
データ相関 元のオブジェクトとメモリを共有せず、完全に独立しています メモリの一部を元のオブジェクトと共有し、1 つを変更すると他のオブジェクトにも影響を与えます
オブジェクト階層 ネストされたデータ構造の場合、すべての子オブジェクトを再帰的にコピーします。 第 1 レベルのオブジェクトのみがコピーされ、ネストされたデータ構造の場合は参照のみがコピーされます。
適用性 複雑なデータ構造を処理し、データの相関によって引き起こされる問題を回避します 単純なデータ構造または共有メモリが必要な状況を処理する
アプリケーションシナリオ 元のデータの変更を防止し、データの履歴ステータスまたはスナップショットを保存します 単純なデータ構造をコピーするための浅いコピーを生成します。
マルチスレッドまたはマルチプロセス環境 マルチスレッドまたはマルチプロセス環境で共有データを操作する マルチスレッドまたはマルチプロセス環境で独立したデータを処理する
再帰的なデータ構造 再帰的なデータ構造を処理して、無限ループや要素の重複を回避します。 大量のデータのコピーを避けるため、浅いコピーに適したデータ構造
メモリ消費量 すべての子オブジェクトがコピーされるため、より多くのメモリが消費される可能性があります メモリの一部を共有することにより、メモリスペースが節約される場合があります。

一般に、ディープ コピーは、複雑なデータ構造の処理、元のデータの変更の防止、データの履歴状態やスナップショットの保存、マルチスレッドまたはマルチプロセス環境での共有データの処理に適しています。浅いコピーは、単純なデータ構造の処理や共有メモリを必要とする状況に適しています。メモリ領域を節約できますが、データの相関関係によって引き起こされる問題に注意する必要があります。コピー方法を選択するときは、特定のアプリケーション シナリオに応じてディープ コピーを使用するかシャロー コピーを使用するかを決定する必要があります。

浅いコピーとポインタ

浅いコピーとポインタは、どちらも共有データの問題を伴うという点で似ています。以下は、浅いコピーとポインタの類似点と相違点の簡単な比較です。

類似点:

  1. 共有メモリ: 浅いコピーとポインタは両方とも共有メモリを必要とします。浅いコピーがオブジェクトをコピーする場合、データ自体ではなくオブジェクトへの参照のみがコピーされるため、コピーされたオブジェクトは元のオブジェクトとメモリの一部を共有します。ポインタは参照を通じてデータにもアクセスするため、ポインタが指すデータと元のデータは共有されます。

  2. 浅いコピー: 浅いコピーとポインターは両方とも、オブジェクトの浅い部分のみをコピーします。浅いコピーでは、第 1 レベルのオブジェクトのみがコピーされ、ネストされたデータ構造への参照のみがコピーされます。ポインタはデータのメモリ アドレスを指すだけで、データ自体はコピーされません。

違い:

  1. データ コピー: オブジェクトをコピーする場合、浅いコピーでは、実際のデータをコピーせずに、オブジェクトの新しいインスタンスを作成し、参照をコピーします。ポインタはデータのメモリ アドレスを指すだけであり、データ自体のコピーは必要ありません。

  2. オブジェクトのプロパティ: 浅いコピーは、オブジェクトの特定のメソッドまたは操作を通じて実行され、オブジェクトのコピー動作です。ポインタは、データのメモリ アドレスを格納するために使用されるデータ型であり、オブジェクトのコピーは必要ありません。

  3. 変更の影響: 浅いコピーの場合、コピーされたオブジェクトへの変更は、メモリの一部を共有するため、元のオブジェクトに影響を与える可能性があります。ポインターの場合、ポインターが指すデータを変更すると、元のデータにも影響します。

要約すると、シャロー コピーとポインタはどちらも共有メモリの問題を伴いますが、本質とアプリケーション シナリオは異なります。浅いコピーは、データ自体のコピーを行わずにオブジェクトの参照をコピーするために使用される特定のオブジェクト コピー動作です。元のデータの変更を防ぎ、データの履歴状態やスナップショットを保存するなどのシナリオに適しています。 。ポインタは、データのメモリ アドレスを格納するために使用されるデータ型で、データにアクセスして変更する必要がある状況に適しています。

おすすめ

転載: blog.csdn.net/qq_40140808/article/details/131902275