1

私は次の状況について混乱しており、おそらく私の語彙がここで間違っているので、申し訳ありません.

タプルがあるx = ('a', [])としますx = (x[0], [1, 2, 3])

新しいタプルは古いタプルを参照しているため、古いタプル オブジェクトを削除することはできませんが、その古いタプル オブジェクトのために x[0] への参照のみを使用しているため、古いタプルの x[1] としてメモリを浪費しています。タプル オブジェクトには何もアクセスできません。

これは正真正銘のメモリ リークのケースですか。新しいタプル オブジェクトの参照が意味を持つようにするためだけにメモリを浪費しているのでしょうか。

4

3 に答える 3

5

おそらく、C++ のような言語から Python に移行することになるでしょう。変数は、値が格納されるメモリの場所です。Python では、値は心配する必要のない場所に格納され、変数はそれらを参照する単なる名前です。値。変数が別の変数を参照するようにする方法はありません*。別の変数と同じを参照するようにすることはできますが、それは問題ではありません。


たとえば、C++ では次のようになります。

int x[] = {1, 2, 3};
int &y = x[0];

ここで、は 3 つの値xを格納するのに十分な大きさのメモリ ロケーションであり、これらのロケーションの最初のものへの参照です。したがって、まだ生きている間に消えてしまうと、ぶら下がっている参照ができてしまい、これは悪いことです。しかし、Pythonでは:intyxy

x = [1, 2, 3]
y = x[0]

ここで、xはオブジェクトの名前であり、その 3 つの位置は別の場所に格納されているlist3 つの異なるオブジェクトの名前であり、最初のオブジェクトの別の名前です。がなくなると、Python は を解放し、その後およびオブジェクト** を解放して (他の誰もそれらを参照しないため)、オブジェクトだけを残します。intyintxlist231


これが、Python に「コピー コンストラクター」*** がない理由でもあります。C++ では、新しいメモリ ロケーションを作成し、 fromをそのメモリ ロケーションにint z = x[0]暗黙的にコピーします。Python では、明示的に のように記述しない限り、何もコピーすることはありません。intx[0]z = copy.copy(x[0])


* これは、閉鎖セルがカバーの下でどのように機能するかを見ると、まったく真実ではありません。

** 実際、小さい整数は通常特別に扱われ、永久に存続しますが、それは無視しましょう。

*** コピー代入演算子、移動コンストラクター、および移動代入演算子ははるかに少なくなります。

于 2013-11-05T20:05:23.620 に答える
4

これは、現在参照されているものと参照されていないものを示すために、あなたの例を使用した注釈付きの Python セッションです。

>>> x = ('a', [])
>>> id(x)
4340112344            # The tuple
>>> id(x[0])
4339406128            # The character 'a'
>>> id(x[1])
4340109184            # An empty list
>>> x = (x[0], [1,2,3])
>>> id(x)
4340112488            # x refers to a new object
>>> id(x[0])
4339406128            # The character 'a'. The old tuple is not involved
>>> id(x[1])
4340199576            # A new list.

元のタプルであるオブジェクト 4340112344 はもはや参照されていないため、 によって参照される新しいオブジェクトに影響を与えることなく、都合のよいときにいつでも自由にガベージ コレクションを行うことができますx

于 2013-11-05T20:03:57.537 に答える
-2

わずかな論理エラー。

Python 文字列は不変です。これを行う場合:

x = ('a', [])

そしてこれ:

x = (x[0], [1,2,3])

x[0]は新しい文字列になりました。つまり、元の文字列に関連付けられていません。したがって、GC は元のタプルを自由に収集できます。

上記は無効です!!! アック!!!!!!!! 間違ったロジック!!! 下のテキストはすべてのタイプに有効です!!!

ただし、これを行った場合:

x = (x[1], 'Hi!')

x[1]リストへの参照であっても、元のタプルは引き続き削除されます。なんで?リストはタプルに関連付けられていないためです。2 つは独立したオブジェクトです。したがって、 を参照するx[1]と、元のタプル自体だけでなく他の要素も安全に削除できます。

結論: オブジェクトが生きていても、その親が生きているとは限りません。上書きし続けるとx、生き続ける必要がある 1 つのオブジェクトを除いて、毎回削除されます。

したがって、メモリリークはありません。

于 2013-11-05T20:02:46.207 に答える