Pythonstring不可变吗?

我的理解是Pythonstring是不可变的。

我试了下面的代码:

a = "Dog" b = "eats" c = "treats" print a, b, c # Dog eats treats print a + " " + b + " " + c # Dog eats treats print a # Dog a = a + " " + b + " " + c print a # Dog eats treats # !!! 

Python不应该阻止这个任务吗? 我可能错过了一些东西。

任何想法?

首先a指向string“狗”。 然后你把variablesa改为指向一个新的string“Dog eats treats”。 你实际上没有改变string“狗”。 string是不可变的,variables可以指向任何他们想要的。

string对象本身是不可变的。

指向string的variablesa是可变的。

考虑:

 a = "Foo" # a now points to "Foo" b = a # b points to the same "Foo" that a points to a = a + a # a points to the new string "FooFoo", but b still points to the old "Foo" print a print b # Outputs: # FooFoo # Foo # Observe that b hasn't changed, even though a has. 

variablesa指向对象“狗”。 最好把Python中的variables看作标记。 您可以将标签移动到不同的对象,这是您将a = "dog"改为a = "dog eats treats"时所做的。

然而,不变性指的是客体,而不是标签。


如果您尝试a[1] = 'z'"dog"变为"dzg" ,则会出现以下错误:

 TypeError: 'str' object does not support item assignment" 

因为string不支持项目分配,因此它们是不可变的。

variables只是一个指向对象的标签。 该对象是不可变的,但是如果你愿意,你可以使标签指向一个完全不同的对象。

只有当我们能够改变内存位置中保存的值而不改变内存位置本身时,东西是可变的。

诀窍是:如果您发现更改前后的内存位置相同,则是可变的。

例如,列表是可变的。 怎么样?

 >> a = ['hello'] >> id(a) 139767295067632 # Now let's modify #1 >> a[0] = "hello new" >> a ['hello new'] Now that we have changed "a", let's see the location of a >> id(a) 139767295067632 so it is the same as before. So we mutated a. So list is mutable. 

一个string是不可变的。 我们如何certificate?

 > a = "hello" > a[0] 'h' # Now let's modify it > a[0] = 'n' ---------------------------------------------------------------------- 

我们得到

TypeError:“str”对象不支持项目分配

所以我们没有突变string。 这意味着一个string是不可改变的。

在你重新分配的时候,你改变这个variables来指向一个新的位置本身。 在这里你没有突变string,而是variables本身。 以下是你在做什么。

 >> a = "hello" >> id(a) 139767308749440 >> a ="world" >> id(a) 139767293625808 

id之前和之后的重新分配是不同的,所以这certificate你实际上没有变异,而是指向variables到新的位置。 这不是突变该string,而是变异该variables。

 l = [1,2,3] print id(l) l.append(4) print id(l) #object l is the same a = "dog" print id(a) a = "cat" print id(a) #object a is a new object, previous one is deleted 

语句a = a + " " + b + " " + c可以根据指针进行细分。

a + " "说给我什么指向,不能改变,并添加" "到我目前的工作集。

记忆:

 working_set = "Dog " a = "Dog" b = "eats" c = "treats" 

+ b说给我什么b点,不能改变,并将其添加到当前的工作集。

记忆:

 working_set = "Dog eats" a = "Dog" b = "eats" c = "treats" 

+ " " + c表示添加" "到当前设置。 然后给我什么c点,不能改变,并将其添加到当前的工作集。 记忆:

 working_set = "Dog eats treats" a = "Dog" b = "eats" c = "treats" 

最后, a =表示设置我的指针指向结果集。

记忆:

 a = "Dog eats treats" b = "eats" c = "treats" 

"Dog"被回收,因为没有更多的指针连接到它的内存块。 我们从来没有修改驻留在内存部分的"Dog" ,这是不可改变的。 但是,我们可以更改哪些标签(如果有的话)指向该部分内存。

数据和它所关联的标签之间是有区别的。 例如,当你这样做

 a = "dog" 

数据"dog"被创build并置于标签a 。 标签可以改变,但是内存中的东西不会。 数据"dog"在内存中仍然存在(直到垃圾回收器删除它)

 a = "cat" 

在你的程序中a现在^指向^ "cat"但string"dog"没有改变。

Pythonstring是不可变的。 但是, a不是一个string:它是一个带有string值的variables。 您不能改变string,但可以将variables的值更改为新的string。

variables可以指向任何他们想要的地方..如果你做以下的事情将会抛出一个错误:

 a = "dog" print a #dog a[1] = "g" #ERROR!!!!!! STRINGS ARE IMMUTABLE 

>>> a = 'dogs'

>>> a.replace('dogs', 'dogs eat treats')

'dogs eat treats'

>>> print a

'dogs'

不可变,不是吗?

variables部分已经被讨论过了。

考虑:

 >>> a='asdf' >>> a.__repr__ <method-wrapper '__repr__' of str object at 0x1091aab90> >>> a='asdf' >>> a.__repr__ <method-wrapper '__repr__' of str object at 0x1091aab90> >>> a='qwer' >>> a.__repr__ <method-wrapper '__repr__' of str object at 0x109198490> 

注意,当我在variables中存储两次相同的值时,hex的内存位置没有改变。 当我存储一个不同的值时,它确实改变了。 该string是不可变的。 不是因为狂热,而是因为你付出了在内存中创build新对象的性能损失。 variablesa只是一个标签指针和内存地址。 它可以改变指向任何东西。

考虑一下你的例子

  a = "Dog" b = "eats" c = "treats" print (a,b,c) #Dog eats treats d = a + " " + b + " " + c print (a) #Dog print (d) #Dog eats treats 

我在博客中find的更准确的解释之一是:

在Python中,(几乎)一切都是一个对象。 我们通常在Python中将其称为“variables”是更合适的名称。 同样,“赋值”实际上是名称与对象的绑定。 每个绑定都有一个定义其可见性的范围,通常是名称所在的块。

例如:

 some_guy = 'Fred' # ... some_guy = 'George' 

当我们稍后说some_guy ='George'时,包含'Fred'的string对象不受影响。 我们刚刚改变了名字some_guy的绑定。 然而,我们还没有改变“弗雷德”或“乔治”string对象。 就我们而言,他们可能无限期地生活下去。

链接到博客: https : //jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/

总结:

 a = 3 b = a a = 3+2 print b # 5 

不可变:

 a = 'OOP' b = a a = 'p'+a print b # OOP 

一成不变的:

 a = [1,2,3] b = range(len(a)) for i in range(len(a)): b[i] = a[i]+1 

这是Python 3中的一个错误,因为它是不可变的。 而不是在Python 2中的错误,因为它显然不是不可变的。

你可以使一个numpy数组不可变,并使用第一个元素:

 numpyarrayname[0] = "write once" 

然后:

 numpyarrayname.setflags(write=False) 

要么

 numpyarrayname.flags.writeable = False