Bagaimana cara menyalin string Python?

92

Saya melakukan ini:

a = 'hello'

Dan sekarang saya hanya ingin salinan independen dari a:

import copy

b = str(a)
c = a[:]
d = a + ''
e = copy.copy(a)

map( id, [ a,b,c,d,e ] )

Keluar [3]:

[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]

Mengapa semuanya memiliki alamat memori yang sama dan bagaimana saya bisa mendapatkan salinannya a?

biasa saya
sumber
3
Untuk mendapatkan jawaban yang berbeda dari Martijin's (yang sepenuhnya benar, meskipun tidak selalu menjawab pertanyaan seperti yang dinyatakan) Anda mungkin ingin memberikan lebih banyak detail / use case untuk menunjukkan mengapa Anda ingin itu disalin.
elmo
4
Seperti yang disiratkan oleh @elemo, ini mungkin Masalah XY .
martineau
2
Saya tertarik untuk memperkirakan penggunaan memori dari kamus bersarang dari formulir d[ 'hello' ] = e, di mana e[ 'hi' ] = 'again'. Untuk menghasilkan kamus bersarang seperti itu, saya membuat satu ekamus dan menyalinnya beberapa kali. Saya perhatikan bahwa konsumsi memori sangat rendah, yang menyebabkan pertanyaan saya di sini. Sekarang saya mengerti bahwa tidak ada salinan string yang dibuat, karenanya konsumsi memori rendah.
biasa saya
1
Jika Anda ingin bmenjadi versi modifikasi atanpa memodifikasi a, biarkan bsaja hasil operasi apa pun. misalnya b = a[2:-1]set bke 'll'dan atetap ' hello'.
OJFord
Ollie benar. Ini karena str adalah tipe yang tidak bisa diubah. Karena penggunaan singletons oleh python (dan mungkin pengoptimalan internal lainnya), Anda tidak akan melihat memori berkembang seperti yang Anda harapkan saat menyalin kamus elektronik.
FizxMike

Jawaban:

137

Anda tidak perlu menyalin string Python. Mereka tidak dapat diubah, dan copymodul selalu mengembalikan aslinya dalam kasus seperti itu, seperti halnya str(), seluruh potongan string, dan digabungkan dengan string kosong.

Selain itu, Anda 'hello'string diinternir ( string tertentu ). Python sengaja mencoba untuk menyimpan hanya satu salinan, karena itu membuat pencarian kamus lebih cepat.

Salah satu cara untuk mengatasinya adalah dengan benar-benar membuat string baru, lalu memotong string itu kembali ke konten aslinya:

>>> a = 'hello'
>>> b = (a + '.')[:-1]
>>> id(a), id(b)
(4435312528, 4435312432)

Tapi yang Anda lakukan sekarang hanyalah membuang memori. Ini tidak seolah-olah Anda dapat mengubah objek string ini dengan cara apa pun.

Jika semua yang ingin Anda ketahui adalah berapa banyak memori yang dibutuhkan objek Python, gunakan sys.getsizeof(); itu memberi Anda jejak memori dari objek Python apa pun.

Untuk wadah, ini tidak termasuk isinya; Anda harus mengulang ke setiap penampung untuk menghitung ukuran memori total:

>>> 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

Anda kemudian dapat memilih untuk menggunakan id()pelacakan untuk mengambil jejak memori yang sebenarnya atau untuk memperkirakan jejak maksimum jika objek tidak di-cache dan digunakan kembali.

Martijn Pieters
sumber
4
Ada lebih dari satu cara untuk membuat objek string baru, seperti b = ''.join(a).
martineau
@martineau: tentu, saya benar-benar bermaksud mengatakan 'satu arah'.
Martijn Pieters
10
Penekanan pada "Anda tidak perlu menyalin string Python". Ada alasan mengapa operasi tersebut mengembalikan string yang sama.
tcooc
1
Dalam kasus ini, OP mencoba membuang memori. Karena dia ingin tahu berapa banyak memori yang akan digunakan oleh sejumlah string, itulah tujuan sebenarnya. Jelas dia bisa menghasilkan string unik, tapi itu hanya pekerjaan yang tidak perlu sebagai solusi.
Gabe
8
+1 untuk "sambil lalu" menggunakan contoh yang menghasilkan 42 .
Bakuriu
11

Anda dapat menyalin string dalam python melalui pemformatan string:

>>> a = 'foo'  
>>> b = '%s' % a  
>>> id(a), id(b)  
(140595444686784, 140595444726400)  
Richard Urban
sumber
4
Tidak benar di Python 3.6.5. id (a) dan id (b) identik. Hasilnya tidak berbeda meskipun saya menggunakan format versi modern, yaitu,b = '{:s}'.format(a)
Seshadri R
7

Saya baru saja memulai beberapa manipulasi string dan menemukan pertanyaan ini. Saya mungkin mencoba melakukan sesuatu seperti OP, "saya yang biasa". Jawaban sebelumnya tidak menjernihkan kebingungan saya, tetapi setelah memikirkannya sedikit, saya akhirnya "mengerti".

Selama a, b, c, d, dan ememiliki nilai yang sama, mereka referensi ke tempat yang sama. Memori disimpan. Begitu variabel mulai memiliki nilai yang berbeda, mereka mulai memiliki referensi yang berbeda. Pengalaman belajar saya berasal dari kode ini:

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

Output yang dicetak adalah:

[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]

hello hello hello hello hello

[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]

goodbye hello hello hello hello something
karl s
sumber
Detail selengkapnya untuk perilaku tersebut dijelaskan dalam posting ini stackoverflow.com/questions/2123925/…
dlasalle
3

Menyalin string dapat dilakukan dengan dua cara, yaitu menyalin lokasi a = "a" b = a atau Anda dapat mengkloning yang berarti b tidak akan terpengaruh ketika a diubah yang dilakukan oleh a = 'a' b = a [:]

Thomas Youngson
sumber
2

Dengan kata lain "id ()" bukanlah yang Anda pedulikan. Anda ingin tahu apakah nama variabel dapat dimodifikasi tanpa merusak nama variabel sumber.

>>> a = 'hello'                                                                                                                                                                                                                                                                                        
>>> b = a[:]                                                                                                                                                                                                                                                                                           
>>> c = a                                                                                                                                                                                                                                                                                              
>>> b += ' world'                                                                                                                                                                                                                                                                                      
>>> c += ', bye'                                                                                                                                                                                                                                                                                       
>>> a                                                                                                                                                                                                                                                                                                  
'hello'                                                                                                                                                                                                                                                                                                
>>> b                                                                                                                                                                                                                                                                                                  
'hello world'                                                                                                                                                                                                                                                                                          
>>> c                                                                                                                                                                                                                                                                                                  
'hello, bye'                                                                                                                                                                                                                                                                                           

Jika Anda terbiasa dengan C, maka ini seperti variabel penunjuk kecuali Anda tidak dapat membatalkan referensi mereka untuk mengubah apa yang mereka tunjuk, tetapi id () akan memberi tahu Anda di mana mereka saat ini menunjuk.

Masalah bagi programmer python muncul ketika Anda mempertimbangkan struktur yang lebih dalam seperti list atau dicts:

>>> o={'a': 10}                                                                                                                                                                                                                                                                                        
>>> x=o                                                                                                                                                                                                                                                                                                
>>> y=o.copy()                                                                                                                                                                                                                                                                                         
>>> x['a'] = 20                                                                                                                                                                                                                                                                                        
>>> y['a'] = 30                                                                                                                                                                                                                                                                                        
>>> o                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> x                                                                                                                                                                                                                                                                                                  
{'a': 20}                                                                                                                                                                                                                                                                                              
>>> y                                                                                                                                                                                                                                                                                                  
{'a': 30}                                                                                                                                                                                                                                                                                              

Di sini o dan x merujuk ke dikt yang sama o ['a'] dan x ['a'], dan dikt itu "bisa berubah" dalam arti bahwa Anda dapat mengubah nilai untuk kunci 'a'. Itulah mengapa "y" perlu menjadi salinan dan y ['a'] bisa merujuk ke sesuatu yang lain.

Charles Thayer
sumber