Python字符串不是不可变的吗?那为什么+""+ b有效呢?

jas*_*son 95 python string immutability mutability

我的理解是Python字符串是不可变的.

我尝试了以下代码:

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
# !!!
Run Code Online (Sandbox Code Playgroud)

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

任何的想法?

Bor*_*ort 164

首先a指向字符串"狗".然后你改变了变量a以指向一个新的字符串"Dog eats treats".你实际上并没有改变字符串"Dog".字符串是不可变的,变量可以指向他们想要的任何东西.

  • 尝试像x ='abc'这样的东西更有说服力; Python repl中的x [1] ='x' (29认同)
  • 如果您想更多地了解内部原理,请参阅我的回答。/sf/answers/2849146611/ (2认同)

Seb*_*olm 49

字符串对象本身是不可变的.

a指向字符串的变量是可变的.

考虑:

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.
Run Code Online (Sandbox Code Playgroud)

  • 取消所有这一切的真正重要的一点是*字符串没有*`append`*函数,因为它们是不可变的.* (6认同)

chr*_*tan 44

变量a指向对象"Dog".最好将Python中的变量视为标记.您可以将标记移动到不同的对象,这是您在更改时所a = "dog"执行的操作a = "dog eats treats".

但是,不变性是指对象,而不是标签.


如果你试图a[1] = 'z'"dog""dzg",你会得到错误:

TypeError: 'str' object does not support item assignment" 
Run Code Online (Sandbox Code Playgroud)

因为字符串不支持项目赋值,因此它们是不可变的.

  • 与其他人相比,这个更清楚! (3认同)

Har*_*nam 13

只有当我们能够更改内存位置中保存的值而不更改内存位置本身时,某些内容才是可变的.

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

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

>> 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.
Run Code Online (Sandbox Code Playgroud)

字符串是不可变的.我们如何证明这一点?

> a = "hello"
> a[0]
'h'
# Now let's modify it
> a[0] = 'n'
----------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

我们得到

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

所以我们没有改变字符串.这意味着字符串是不可变的.

在重新分配时,您将变量更改为指向新位置本身.在这里你没有改变字符串,但改变了变量本身.以下是您正在做的事情.

>> a = "hello"
>> id(a)
139767308749440
>> a ="world"
>> id(a)
139767293625808
Run Code Online (Sandbox Code Playgroud)

id在重新分配之前和之后是不同的,所以这证明你实际上没有变异,而是将变量指向新位置.这不是改变那个字符串,而是改变那个变量.


jco*_*ado 11

变量只是指向对象的标签.该对象是不可变的,但如果您愿意,可以使标签指向完全不同的对象.


Bru*_*sky 8

考虑:

>>> 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>
Run Code Online (Sandbox Code Playgroud)

请注意,当我在变量中存储相同的值两次时,十六进制内存位置没有改变.当我存储不同的值时它确实发生了变化.字符串是不可变的.不是因为狂热,而是因为你付出了在内存中创建新对象的性能损失.变量a只是指向该内存地址的标签.它可以改为指向任何东西.


Spe*_*bun 7

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

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

记忆:

working_set = "Dog "
a = "Dog" 
b = "eats"
c = "treats"
Run Code Online (Sandbox Code Playgroud)

+ b说给我什么b指向,不能改变,并将其添加到当前工作集.

记忆:

working_set = "Dog eats"
a = "Dog" 
b = "eats"
c = "treats"
Run Code Online (Sandbox Code Playgroud)

+ " " + c说添加" "到当前集.然后给我c指出哪些不能改变,并将其添加到当前工作集.记忆:

working_set = "Dog eats treats"
a = "Dog" 
b = "eats"
c = "treats"
Run Code Online (Sandbox Code Playgroud)

最后,a =说设置我的指针指向结果集.

记忆:

a = "Dog eats treats"
b = "eats"
c = "treats"
Run Code Online (Sandbox Code Playgroud)

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


use*_*629 6

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
Run Code Online (Sandbox Code Playgroud)


mit*_*tch 5

数据与其关联的标签之间存在差异.例如,当你这样做

a = "dog"
Run Code Online (Sandbox Code Playgroud)

数据"dog"被创建并放在标签下a.标签可以改变,但内存中的内容不会改变."dog"在您执行之后,数据仍将存在于内存中(直到垃圾收集器将其删除)

a = "cat"
Run Code Online (Sandbox Code Playgroud)

在你的程序中,a现在^指向^ "cat"但字符串"dog"没有改变.