如何复制Python字符串?


92

我这样做:

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


3
要获得与Martijin的答案不同的答案(这是完全正确的,尽管不一定回答所陈述的问题),您可能需要提供更多详细信息/用例以说明为什么要复制它。
Elmo 2014年

4
正如@elemo所暗示的,这可能是XY问题
martineau 2014年

2
我对估算嵌套式形式d[ 'hello' ] = ewhere的字典的内存使用情况很感兴趣e[ 'hi' ] = 'again'。为了生成这样的嵌套字典,我生成了一个e字典并多次复制了它。我注意到内存消耗非常低,这引起了我的疑问。现在我知道没有创建字符串副本,因此内存消耗低。
平常我

1
如果要b成为a不修改的修改版本a,只需让它b成为任何操作的结果即可。例如,b = a[2:-1]b'll'a遗体“ hello'
OJFord 2014年

奥利是正确的。这是因为str是不可变的类型。由于python使用单例(可能还有其他内部优化方法),因此您在复制e字典时不会看到预期的内存扩展。
FizxMike

Answers:


137

无需复制Python字符串。它们是不可变的,copy在这种情况下,模块始终返回原始值,例如do str(),整个字符串切片,并与空字符串连接。

此外,您的'hello'字符串已被扣留某些字符串是)。Python故意尝试仅保留一个副本,因为这会使字典查找更快。

解决此问题的一种方法是实际创建一个新字符串,然后将该字符串切回到原始内容:

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

但是您现在要做的只是浪费内存。毕竟,似乎您无法以任何方式使这些字符串对象发生变异。

如果您只想知道Python对象需要多少内存,请使用sys.getsizeof(); 它为您提供了任何Python对象的内存占用量。

对于集装箱这并没有包括的内容; 您必须递归到每个容器中以计算总内存大小:

>>> 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()如果未缓存和重用对象,则可以选择使用跟踪来获取实际的内存占用空间或估计最大占用空间。


4
创建新字符串对象的方法不止一种,例如b = ''.join(a)
martineau 2014年

@martineau:当然,我真的想说“单向”。
的Martijn Pieters的

10
强调“您不需要复制Python字符串”。这些操作仅返回相同的字符串是有原因的。
tcooc

1
但是,在这种情况下,OP尝试浪费内存。由于他想知道一定数量的字符串将使用多少内存,因此这是实际目标。显然,他可以生成唯一的字符串,但这只是解决该问题的不必要工作。
加布2014年

8
使用将输出42的示例为“偶然” +1 。
Bakuriu 2014年

11

您可以通过字符串格式在python中复制字符串:

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

4
在Python 3.6.5中不正确。id(a)和id(b)相同。结果并没有什么不同,甚至当我使用的格式,即现代版。b = '{:s}'.format(a)
Seshadri [R

7

我刚刚开始一些字符串操作,发现了这个问题。我可能正在尝试执行OP,“通常是我”。先前的答案并没有消除我的困惑,但是经过一番思考之后,我终于“明白了”。

只要abcd,并且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

对于行为的更多细节在这个职位描述stackoverflow.com/questions/2123925/...
dlasalle

3

复制字符串可以通过两种方式完成,要么复制位置a =“ a” b = a,要么可以克隆,这意味着当a更改时,b将不会受到影响,这是通过a ='a'b = a [:]完成的


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指的是相同的dict o ['a']和x ['a'],并且该dict是“可变的”,因为您可以更改键“ a”的值。这就是为什么“ y”需要为副本,而y ['a']可以引用其他内容的原因。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.