私はこれをします:
a = 'hello'
そして今、私はa
の独立したコピーが欲しいだけです:
import copy
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
map( id, [ a,b,c,d,e ] )
アウト[3]:
[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]
なぜ彼らはすべて同じメモリアドレスを持っているのですか?どのようにしてa
のコピーを取得できますか?
Python文字列をコピーする必要はありません。これらは不変であり、copy
モジュールは、str()
、文字列スライス全体、空の文字列との連結など、常にそのような場合に元のものを返します。
さらに、'hello'
文字列はinterned(- 特定の文字列は )です。 Pythonは1つのコピーのみを意図的に保持しようとします。これにより、辞書検索が高速になります。
これを回避する方法の1つは、実際に新しい文字列を作成し、その文字列を元のコンテンツにスライスすることです。
>>> a = 'hello'
>>> b = (a + '.')[:-1]
>>> id(a), id(b)
(4435312528, 4435312432)
しかし、あなたが今しているのはメモリの浪費だけです。結局のところ、これらの文字列オブジェクトを何らかの方法で変更できるというわけではありません。
Pythonオブジェクトに必要なメモリ量だけを知りたい場合は、 sys.getsizeof()
を使用します。 Pythonオブジェクトのメモリフットプリントを提供します。
コンテナの場合、これには内容が含まれませんnot;合計メモリサイズを計算するには、各コンテナに再帰する必要があります。
>>> import sys
>>> a = 'hello'
>>> sys.getsizeof(a)
42
>>> b = {'foo': 'bar'}
>>> sys.getsizeof(b)
280
>>> sys.getsizeof(b) + sum(sys.getsizeof(k) + sys.getsizeof(v) for k, v in b.items())
360
その後、id()
トラッキングを使用して、実際のメモリフットプリントを取得するか、オブジェクトがキャッシュおよび再利用されなかった場合の最大フットプリントを推定することを選択できます。
文字列の書式設定により、pythonの文字列をコピーできます。
>>> a = 'foo'
>>> b = '%s' % a
>>> id(a), id(b)
(140595444686784, 140595444726400)
文字列操作を始めたばかりで、この質問を見つけました。私はおそらく、OPのような何か、「通常の私」をやろうとしていました。これまでの回答では混乱は解消しませんでしたが、少し考えた後、やっと「わかった」。
a
、b
、c
、d
、およびe
の値が同じである限り、それらは同じ場所を参照します。メモリが保存されます。変数が異なる値を持つようになるとすぐに、変数は異なる参照を持つようになります。私の学習経験はこのコードから来ました:
import copy
a = 'hello'
b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)
print map( id, [ a,b,c,d,e ] )
print a, b, c, d, e
e = a + 'something'
a = 'goodbye'
print map( id, [ a,b,c,d,e ] )
print a, b, c, d, e
印刷出力は次のとおりです。
[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]
hello hello hello hello hello
[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]
goodbye hello hello hello hello something
文字列のコピーは、a = "a" b = aの場所をコピーするか、a = 'a' b = a [:]でaが変更されたときにbが影響を受けないという2つの方法で実行できます。
別の言い方をすれば、「id()」は気にすることではありません。ソース変数名に影響を与えずに変数名を変更できるかどうかを知りたい。
>>> a = 'hello'
>>> b = a[:]
>>> c = a
>>> b += ' world'
>>> c += ', bye'
>>> a
'hello'
>>> b
'hello world'
>>> c
'hello, bye'
Cに慣れている場合、これらはポインター変数に似ていますが、参照先を変更して参照することはできませんが、id()は現在の位置を示します。
pythonプログラマーの問題は、リストや辞書などのより深い構造を考慮すると発生します。
>>> o={'a': 10}
>>> x=o
>>> y=o.copy()
>>> x['a'] = 20
>>> y['a'] = 30
>>> o
{'a': 20}
>>> x
{'a': 20}
>>> y
{'a': 30}
ここで、oとxは同じ辞書o ['a']とx ['a']を指し、その辞書はキー 'a'の値を変更できるという意味で「可変」です。そのため、「y」はコピーである必要があり、y ['a']は他の何かを参照できます。