Python変数付与時の参照伝達問題

9074 ワード

  • 変数付与時の参照転送
  • 可変オブジェクトおよび非可変オブジェクト
  • Pythonメモリ割当て
  • 変数付与時の参照転送
    Python言語では、オブジェクトは参照によって伝達されます.値を割り当てると、オブジェクトが新しく作成された場合でも、既存のオブジェクトでも、オブジェクトの参照(値ではない)が変数に割り当てられます.
    Pythonは、メモリ内のオブジェクトを追跡するために参照カウントという簡単な技術を使用しています.つまりPythonの内部には,すべての使用中のオブジェクトがどれだけの参照を持っているかが記録されている.参照カウンタと呼ばれる内部追跡変数.各オブジェクトにはそれぞれ何個の参照があり、参照カウントと略称されます.オブジェクトが作成されると、リファレンスカウントが作成され、そのオブジェクトが不要になった場合、すなわち、このオブジェクトのリファレンスカウントが0になった場合、ゴミ回収されます.
      オブジェクトが作成され、変数に値が割り当てられた場合、そのオブジェクトの参照数は1に設定されます.同じオブジェクト(の参照)が他の変数に割り当てられた場合、またはパラメータとして関数、メソッド、クラスインスタンスに渡された場合、またはウィンドウオブジェクトのメンバーに割り当てられた場合、オブジェクトの新しい参照、または別名と呼ばれ、作成されます(オブジェクトの参照カウントは自動的に1が加算されます).
    オブジェクトのリファレンスが破棄されると、リファレンス数が減少します.最も明らかな例は、参照がその役割範囲から離れると、関数の実行が終了すると、すべてのローカル変数が自動的に破棄され、オブジェクトの参照カウントが減少することが最もよくあります.変数が別のオブジェクトに割り当てられると、元のオブジェクトの参照カウントも自動的に1減少します.オブジェクトの参照カウントが減少する他の方法は、del文を使用して変数を削除するか、オブジェクトがウィンドウオブジェクトから移動された場合(または、コンテナオブジェクト自体の参照カウントが0になった場合)を含む.
    >>> a = 1
    >>> b = a
    >>> id(a), id(b)
    (1386769424, 1386769424)
    >>> a = 2
    >>> a, b
    (2, 1)
    >>> id(a), id(b)
    (1386769456, 1386769424)

      上記の例では、a = 1使変数aは整数オブジェクト1を指し、b = a使変数bも整数オブジェクト1を指し、文id(a), id(b)から変数aと変数bが指すメモリアドレスが同じであることがわかる.
      文a = 2は、新しいオブジェクト2を変数aに割り当て、このとき変数aはオブジェクト2を指し、変数bは元のオブジェクト1を指す.文id(a), id(b)によって、変数aと変数bが指すメモリアドレスが異なることがわかります.
    可変オブジェクトと非可変オブジェクト
    Python言語のオブジェクトは、可変オブジェクトと可変オブジェクトに分けられます.
  • 可変オブジェクト.このオブジェクトが指すメモリの値は変更できません.ある変数を変更すると、その値が変更できないため、元の値をコピーして変更することに相当し、新しいアドレスが開き、変数がこの新しいアドレスを指します.
  • 可変オブジェクト.このオブジェクトが指すメモリの値を変更することができる.変数(正確には参照)が変更されると、実際にはその値が直接変更され、複製行為も発生せず、新しいアドレスも開発されず、通俗的にはその場で変更される.

  • 数値、文字列、およびメタグループは可変タイプであり、リストおよび辞書は可変タイプである.
    >>> a = 1
    >>> id(a)
    1386769424
    >>> a = a + 1
    >>> a
    2
    >>> id(a)
    1386769456

      上記の例では、文a = a + 1が変数aの値を変更した場合、変数aが指すオブジェクト1は可変オブジェクトであるため、新しいオブジェクト2が作成され、変数aがオブジェクト2を指すようになった.
    >>> a = (1, 2, 3)
    >>> id(a)
    305934860864
    >>> a = a + (4, 5, 6)
    >>> a
    (1, 2, 3, 4, 5, 6)
    >>> id(a)
    305934762152

    メタグループを使用した結果は、整数オブジェクトと同じであることがわかります.
    >>> a = [1, 2, 3]
    >>> b = a
    >>> id(a), id(b)
    (305934751624, 305934751624)
    >>> b += [4, 5, 6]
    >>> a, b
    ([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6])
    >>> id(a), id(b)
    (305934751624, 305934751624)

    上記は可変オブジェクトの一例であり、変数aと変数bは同時にリストオブジェクト[1, 2, 3]を指し、文b += [4, 5, 6]が変数bの値を変更すると、新しいリストオブジェクトは作成されず、元の変数aと変数bが指すリストオブジェクトが直接変更される.
    Pythonではa += ba = a + bに違いがあります.a += b変数aを直接操作すると、変数aの値が変更されます.a = a + bでは、a + bは新しいオブジェクトを生成し、変数aはこの新しいオブジェクトを指します.
    >>> a = [1, 2, 3]
    >>> b = a
    >>> id(a), id(b)
    (305934751176, 305934751176)
    >>> b = b + [4, 5, 6]
    >>> a, b
    ([1, 2, 3], [1, 2, 3, 4, 5, 6])
    >>> id(a), id(b)
    (305934751176, 305939124168)

    Pythonメモリ割り当て
    Pythonでは、表示されるオブジェクトごとにメモリが割り当てられます.値が完全に等しい場合でも(同じかどうかは注意してください).a = 2.0を実行すると、b = 2.0の2つの文は、2.0というFloatタイプのオブジェクトにメモリを割り当て、abをそれぞれ2つのオブジェクトに割り当てます.したがって、abは同じオブジェクトを指していません.
    >>> a = 2.0
    >>> b = 2.0
    >>> a is b
    False
    >>> a == b
    True

    ただし、メモリの使用効率を向上させるために、数値の小さいintオブジェクトのような簡単なオブジェクトについては、Pythonはa = 2を実行するなど、オブジェクトメモリを再利用する方法を採用している.b = 2を実行する場合、2は単純なintタイプとして数値が小さいため、Pythonはメモリを2回割り当てるのではなく、1回だけ割り当てる.次に、abを同時に割り当てられたオブジェクトに指定します.
    >>> a = 2
    >>> b = 2
    >>> a is b
    True

      2ではなく大きな数値を付与すると、前のものと同じになります.
    >>> a = 5555
    >>> b = 5555
    >>> a is b
    False
    >>> id(a)
    12464372
    >>> id(b)
    12464396

    2つのオブジェクトは、値が等しくても異なるオブジェクトです.
    >>> id(12345)
    305935347440
    >>> id(12345)
    305935347152

    参考文献[1]Pythonコアプログラミング(第2版)[2]https://www.cnblogs.com/sun-haiyu/p/7096918.html [3] https://blog.csdn.net/weixin_36250487/article/details/79620874