如何复制 Python 字符串?

我这样做:

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的副本?

241346 次浏览

You don't need to copy a Python string. They are immutable, and the copy module always returns the original in such cases, as do str(), the whole string slice, and concatenating with an empty string.

此外,您的 '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()跟踪来获取实际的内存占用量,或者在对象没有缓存和重用的情况下估计最大的内存占用量。

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

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

复制字符串可以有两种方式: 复制位置 a = “ a”b = a 或者你可以克隆,这意味着当 a 被改变时 b 不会受到影响,这是由 a = ‘ a’b = a [ : ]完成的

我刚开始一些字符串操作,发现了这个问题。我可能是想做一些像观察所那样的事情,“平常的我”。以前的回答并没有解决我的困惑,但是经过一番思考之后,我终于“明白了”。

只要 abcde具有相同的值,它们就引用相同的位置。保存内存。一旦变量开始具有不同的值,它们就开始具有不同的引用。我的学习经验来自这段代码:

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

换一种说法“ id ()”并不是您所关心的。您想知道是否可以在不损害源变量名的情况下修改变量名。

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

如果你习惯于 C 语言,那么它们就像指针变量一样,只是你不能解引用它们来修改它们指向的地方,但是 id ()会告诉你它们当前指向的地方。

The problem for python programmers comes when you consider deeper structures like lists or dicts:

>>> 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 指的是同一个 dicto [‘ a’]和 x [‘ a’] ,这个 dict 是“可变的”,意思是你可以改变键‘ a’的值。这就是为什么“ y”需要是一个拷贝,而 y [‘ a’]可以指代其他东西。

正如其他人已经解释过的那样,实际上很少需要这样做,但不管怎样,你还是要这样做:
(可以在 Python3上工作,但是对于 Python2可能有类似的东西)

import ctypes


copy          = ctypes.pythonapi._PyUnicode_Copy
copy.argtypes = [ctypes.py_object]
copy.restype  = ctypes.py_object


s1 = 'xxxxxxxxxxxxx'
s2 = copy(s1)


id(s1) == id(s2) # False

这是可能的,使用这个简单的技巧:

a = "Python"
b = a[ : : -1 ][ : : -1 ]
print( "a =" , a )
print( "b =" , b )
a == b  # True
id( a ) == id( b ) # False

我想我刚刚用切线解决了这个问题。

a="words"
b=a[:int(len(a)/2)]+a[int(len(a)/2):]
b
'words'
id(a),id(b)
(1492873997808, 1492902431216)