Bir Python dizesini nasıl kopyalayabilirim?


92

Bunu yapıyorum:

a = 'hello'

Ve şimdi şunun bağımsız bir kopyasını istiyorum a:

import copy

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

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

Çıkış [3]:

[4365576160, 4365576160, 4365576160, 4365576160, 4365576160]

Neden hepsi aynı hafıza adresine sahip ve bir kopyasını nasıl alabilirim a?


3
Martijin'in yanıtından farklı bir yanıt almak için (ki bu tamamen doğrudur, ancak soruyu belirtildiği gibi yanıtlaması gerekmez), neden kopyalanmasını istediğinizi göstermek için daha fazla ayrıntı / kullanım örneği sağlamak isteyebilirsiniz.
elmo

4
@Elemo'nun ima ettiği gibi, bu bir XY Problemi olabilir .
martineau

2
Formun iç içe geçmiş bir sözlüğünün bellek kullanımını tahmin etmekle ilgileniyordum d[ 'hello' ] = e, burada e[ 'hi' ] = 'again'. Böyle iç içe geçmiş bir sözlük oluşturmak için tek bir esözlük oluşturdum ve bunu birçok kez kopyaladım. Hafıza tüketiminin çok düşük olduğunu fark ettim, bu da soruma burada yol açtı. Artık hiçbir dize kopyasının oluşturulmadığını anlıyorum, bu nedenle düşük bellek tüketimi.
her zamanki ben

1
İsterseniz bdeğiştirilmiş bir sürümü olmayı adeğiştirmeden a, sadece izin bne olursa olsun operasyon sonucu. örneğin b = a[2:-1]setleri biçin 'll've akalıntılar ' hello'.
OJFord

Ollie haklı. Bunun nedeni, str'nin değişmez bir tür olmasıdır. Python'un tekil kullanması (ve muhtemelen diğer dahili optimizasyonlar) nedeniyle, e sözlüğünü kopyalarken belleğin beklediğiniz gibi genişlediğini görmeyeceksiniz.
FizxMike

Yanıtlar:


137

Bir Python dizesini kopyalamanıza gerek yok . Değişmezler ve copymodül, bu gibi durumlarda, str()tüm dize dilimini ve boş bir dizeyle birleştirerek her zaman orijinali döndürür .

Üstelik senin 'hello'dize edilir enterne ( bazı dizeleri ). Python kasıtlı olarak sadece bir kopyayı tutmaya çalışır, çünkü bu sözlük aramalarını daha hızlı yapar.

Bunu aşmanın bir yolu, aslında yeni bir dize oluşturmak ve ardından bu dizeyi orijinal içeriğe geri dilimlemektir:

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

Ama şu anda yaptığınız tek şey boş hafıza. Sonuçta, bu dizgi nesnelerini herhangi bir şekilde değiştirebilecekmişsiniz gibi değil.

Tek bilmek istediğiniz, bir Python nesnesinin ne kadar bellek gerektirdiğiyse, şunu kullanın sys.getsizeof(); size herhangi bir Python nesnesinin bellek ayak izini verir.

Kaplar için bu etmez olmayan içerikleri içerir; toplam bellek boyutunu hesaplamak için her bir kabın içinde tekrarlamanız gerekir:

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

Daha sonra id(), gerçek bir bellek ayak izini almak için veya nesneler önbelleğe alınmadıysa ve yeniden kullanılmadıysa maksimum ayak izini tahmin etmek için izlemeyi kullanmayı seçebilirsiniz .


4
Yeni bir dizgi nesnesi oluşturmanın birden fazla yolu vardır, örneğin b = ''.join(a).
martineau

@martineau: tabii, gerçekten 'tek yol' demek istedim.
Martijn Pieters

10
"Bir Python dizesini kopyalamanıza gerek yok" üzerine vurgu. Bu işlemlerin aynı dizeyi döndürmesinin bir nedeni var.
tcooc

1
Bu durumda, OP hafızayı boşa harcamaya çalışıyor. Belli sayıda dizge tarafından ne kadar bellek kullanılacağını bilmek istediğinden, asıl amaç budur. Açıkçası benzersiz dizeler üretebilirdi, ancak bu bir geçici çözüm olarak sadece gereksiz bir iş.
Gabe

8
42 çıktı verecek bir örnek kullanarak "gelişigüzel" için +1 .
Bakuriu

11

Bir dizeyi python'da dize biçimlendirme yoluyla kopyalayabilirsiniz:

>>> a = 'foo'  
>>> b = '%s' % a  
>>> id(a), id(b)  
(140595444686784, 140595444726400)  

4
Python 3.6.5'te doğru değil. id (a) ve id (b) aynıdır. Formatın modern versiyonunu kullandığım zaman bile sonuçlar farklı değilb = '{:s}'.format(a)
Seshadri R

7

Sadece bazı dizi manipülasyonlarına başlıyorum ve bu soruyu buldum. Muhtemelen OP gibi bir şey yapmaya çalışıyordum, "her zamanki ben". Önceki cevaplar kafa karışıklığımı gidermedi, ancak biraz düşündükten sonra nihayet "anladım".

Sürece a, b, c, d, ve eaynı değere sahip, bunlar aynı yere başvurur. Hafıza kaydedilir. Değişken farklı değerlere sahip olmaya başlar başlamaz, farklı referanslara sahip olmaya başlarlar. Öğrenme deneyimim şu koddan geldi:

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

Yazdırılan çıktı:

[4538504992, 4538504992, 4538504992, 4538504992, 4538504992]

hello hello hello hello hello

[6113502048, 4538504992, 4538504992, 4538504992, 5570935808]

goodbye hello hello hello hello something

Davranışla ilgili daha fazla ayrıntı bu yazıda açıklanmıştır stackoverflow.com/questions/2123925/…
dlasalle

3

Bir dizeyi kopyalamak iki şekilde yapılabilir ya a = "a" b = a konumunu kopyalayın veya klonlayabilirsiniz, bu da a değiştiğinde b'nin etkilenmeyeceği anlamına gelir, bu a = 'a' b = a [:] ile yapılır.


2

Başka bir deyişle "id ()" umursadığınız şey değil. Değişken adının kaynak değişken adına zarar vermeden değiştirilip değiştirilemeyeceğini bilmek istersiniz.

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

C'ye alışkınsanız, bunlar işaretçi değişkenleri gibidir, ancak gösterdikleri şeyi değiştirmek için referanslarını kaldıramazsınız, ancak id () size şu anda nereye işaret ettiklerini söyleyecektir.

Python programcıları için sorun, listeler veya dikteler gibi daha derin yapıları düşündüğünüzde ortaya çıkar:

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

Burada o ve x aynı dikteye o ['a'] ve x ['a'] atıfta bulunur ve bu dikte, 'a' anahtarının değerini değiştirebilmeniz açısından "değiştirilebilir" dir. Bu nedenle "y" nin bir kopya olması gerekir ve y ['a'] başka bir şeye başvurabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.