Pythonにおける変数の付与/浅いコピー/深いコピーの役割分析

20489 ワード

Pythonにおける変数の付与,浅いコピー,深いコピーについては,いくつかの文章を見てもよく理解できなかったので,自分で簡単な実験で検証した.  付与、浅いコピー、深いコピーの役割を明らかにするには、pythonにおける参照とオブジェクトに関する概念を理解する必要があります.次の簡単なコードを例に挙げます.
a = 2
b = 2

上のコードでは,2はオブジェクトであり,変数aと変数bはいずれも2の参照(アドレス)である.すなわち、pythonでは、新しい変数がオブジェクトに参照を追加します.複数の変数がマッピングされているオブジェクトの内容が完全に同じである場合、実際には同じオブジェクトがマッピングされます.Pythonでは、オブジェクトはその内容に応じて可変オブジェクトと可変オブジェクトに分けられます.
  • 可変オブジェクト:リスト、辞書
  • 可変オブジェクト:数値(int/float)、文字列、メタグループ
  • 次に,付与,浅いコピー,深いコピーを実験により具体的に認識する.可変オブジェクト、単純可変オブジェクト(サブエレメントが可変オブジェクトである)、および複雑な可変オブジェクト(サブエレメントに可変オブジェクトが含まれている)に対するそれらの役割をそれぞれ検証します.可変オブジェクト:
    import copy 
    
    a = 1
    b = a
    c = copy.copy(a)
    d = copy.deepcopy(a)
    print(id(a), id(b), id(c), id(d))  # 1690462992 1690462992 1690462992 1690462992
    a = 2
    print(a, b, c, d)  # 2 1 1 1
    print(id(a), id(b), id(c), id(d))  # 1690463024 1690462992 1690462992 1690462992
    

     可変オブジェクトでは、付与、浅いコピー、深いコピーは新しいオブジェクトを作成せず、既存のオブジェクトの参照を追加します.aの値を変更することは、変数aを新しいオブジェクト2にマッピングするので、aのアドレスが変更される.同時に、オブジェクト1の参照カウントは1減少する.変数b,c,dは依然としてオブジェクト1の参照であり,値はいずれも変わらない.
    単純可変オブジェクト:
    import copy
    
    a = [1, 1]
    b = a
    c = copy.copy(a)
    d = copy.deepcopy(a)
    print(id(a), id(b), id(c), id(d))  # 2735941969160 2735941969160 2735941969416 2735941970568
    print(id(a[0]), id(a[1]))  # 1690462992 1690462992
    print(id(b[0]), id(b[1]))  # 1690462992 1690462992
    print(id(c[0]), id(c[1]))  # 1690462992 1690462992
    print(id(d[0]), id(d[1]))  # 1690462992 1690462992
    a[0] = 2
    print(id(a), id(b), id(c), id(d))  # 2735941969160 2735941969160 2735941969416 2735941970568
    print(id(a[0]), id(a[1]))  # 1690463024 1690462992
    print(id(b[0]), id(b[1]))  # 1690463024 1690462992
    print(id(c[0]), id(c[1]))  # 1690462992 1690462992
    print(id(d[0]), id(d[1]))  # 1690462992 1690462992
    

    単純可変オブジェクトの場合、付与値は元のオブジェクトの参照を増加させるだけです.ただし、このとき、浅いコピーと深いコピーは別々にメモリを開いて新しいオブジェクトを作成するが、新しいオブジェクトの要素1は既に存在するオブジェクトであるため、このサブ要素は最初の1オブジェクトにマッピングされる(注意id(a)はlistオブジェクトのアドレスであり、id(a[i])はlistのi番目の要素がマッピングされるオブジェクトのアドレスである).a[0]を変更すると、bはaの別名に相当するため、bは変更されるが、c、dはいずれも新しいオブジェクトにマッピングされるため、影響を受けない.
    複雑な可変オブジェクト:
    import copy
    
    a = [1, [2, 2]]
    b = a
    c = copy.copy(a)
    d = copy.deepcopy(a)
    print(id(a), id(b), id(c), id(d))  # 2735941970440 2735941970440 2735941969160 2735941969416
    print(id(a[0]), id(a[1]))  # 1690462992 2735941970504
    print(id(b[0]), id(b[1]))  # 1690462992 2735941970504
    print(id(c[0]), id(c[1]))  # 1690462992 2735941970504
    print(id(d[0]), id(d[1]))  # 1690462992 2735941970376
    a[1].append(2)
    print(id(a), id(b), id(c), id(d))  # 2735941970440 2735941970440 2735941969160 2735941969416
    print(id(a[0]), id(a[1]))  # 1690462992 2735941970504
    print(id(b[0]), id(b[1]))  # 1690462992 2735941970504
    print(id(c[0]), id(c[1]))  # 1690462992 2735941970504
    print(id(d[0]), id(d[1]))  # 1690462992 2735941970376
    

    複雑な可変オブジェクトに対して、元のオブジェクトの参照を追加し、浅いコピーと深いコピーを新しいオブジェクトにマッピングします.異なる点は、浅いコピーは、サブエレメント内の可変オブジェクトに新しいメモリを開くのではなく、深いコピーになります.従って、a中の可変オブジェクトを変更すると、b、cはいずれも変化し、dは影響を受けない.
    まとめ:
  • 賦値は、すべてのオブジェクトにとって、オブジェクトの参照を増やす役割を果たす.
  • 浅いコピー可変オブジェクトについて:オブジェクト参照を追加する;単純可変オブジェクトの場合:新しいオブジェクトを作成します.複雑な可変オブジェクトの場合:最上位の可変オブジェクトに新しいオブジェクトを作成し、サブ可変オブジェクトに対して元のオブジェクト参照を追加するだけです.
  • 深度コピー可変オブジェクトについて:オブジェクト参照を追加する;可変オブジェクトの場合:すべての階層の可変オブジェクトに新しいオブジェクトを作成します.