为什么字符串对象在python中缓存

时间:2013-12-08 12:53:44

标签: python string

以下是示例:

>>> first_string = str('This_is_some_how_cached')
>>> second_string = str('This_is_some_how_cached')
>>> id(first_string) == id(second_string)
True
>>> first_string = str('This_is_new_string')
>>> second_string
'This_is_some_how_cached'
>>>

在上面的例子中,first_string和second_string是以不同的方式创建的,但它们具有相同的id,这意味着它们指向相同的引用?如果是,当我将first_string更改为某个新字符串时,不会更新second_string。字符串类中的这个python __new__方法是否对小字符串或?进行缓存?

有人可以解释一下吗?

3 个答案:

答案 0 :(得分:4)

有一个原因,为什么修改字符串不是goint来修改第二个字符串。

python中的字符串是不可变的。

并不完全是字符串在python中缓存,但事实是你无法改变它们。 python解释器能够稍微优化并将两个名称引用到相同的id。

在python中,你永远不会直接编辑字符串。看看这个:

a = "fun"
a.capitalize()
print a
>> fun

大写功能将创建a的大写版本,但不会更改a。一个例子是str.replace。您可能已经注意到,要使用replace更改字符串,您必须执行以下操作:

a = "fun"
a = a.replace("u", "a")
print a
>> fan

您在此处看到的是名称a正在影响指向“有趣”的指针。在第二行,如果没有相似的字符串,我们会影响{​​{1}}的新ID,旧的a可能会被gc删除。

你必须要理解的是,因为字符串是不可变的,所以python可以安全地将字符串指向同一个id。由于字符串永远不会被修改。你不能拥有一个会被隐含修改的字符串。

此外,您会看到其他类型的数字也是不可变的,并且与ids的行为相同。但不要被ids愚弄,因为出于某些原因,我无法解释。

任何大于256的数字都会收到不同的ID,即使它们指向相同的值。如果我没弄错的话,使用更大的字符串,ID也会有所不同。

注意:

在repl或程序本身内部评估代码​​时,id事物也可能具有不同的值。我记得有一个代码使用代码块进行优化。这意味着在不同的行上执行代码可能足以阻止优化。

以下是REPL中的一个示例:

a

有了数字:

>>> a = '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'; b = '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> id(a), id(b)
(4561897488, 4561897488)

>>> a = '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> b = '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]'
>>> id(a), id(b)
(4561897416, 4561897632)

但是作为python脚本执行文件会打印,因为它执行相同代码块中的行(据我所知)

>>> a = 100000
>>> b = 100000
>>> id(a), id(b)
(140533800516256, 140533800516304)

>>> a = 100000; b = 100000 
>>> id(a), id(b)
(140533800516232, 140533800516232) 

答案 1 :(得分:2)

字符串不会被缓存 - 它们实际上是相同的字符串。

请参阅,Python中的字符串是不可变的。就像数字1相同的数字1一样,无论您在代码中的哪个位置编写它,字符串"Hello"都是相同 string,无论你在代码中的哪个位置写它。

由于它是不可变的,你也不能像列表或某些内容那样就地更改它 - 例如,如果你调用list.reverse(),它会更改原始列表,但是如果你调用{{1它,返回一个新字符串,旧字符串不受影响(这意味着它是不可变的)。因为你不能改变那个字符串,所以Python中有两个不同的str.replace("a", "b")副本没有任何意义,因为它们都意味着完全相同的东西而都不会改变。< / em>的

编辑 - @Keeper指出,有一个section of the Python FAQ详细说明为什么字符串是不可变的,因此它们的行为就像这样。 Link

答案 2 :(得分:0)

python中的字符串未缓存:)

a = 'a'
b = 'a'
id(a) == id(b) = id('a') # True because share same constant object id('a')!
a = 'z' # it change 'a' but a is not referencing 'b' so you can not change b
id(a) == id('z') # not a contains 'z' but since not related to b, b contains still 'a'!

你可以做这样的事情来实现你想要的:

Thing(object): # Dummy object can store any field since it is Python
  pass

a = Thing()
a.str = 'a'
b = a 
print b.str # return 'a' since reference to object is same!

a.str = 'b'

print b.str # return 'b' since reference to object is same but value changed!