问题:Python字符串不是一成不变的吗?那么为什么a +“” + b有效呢?

我的理解是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
# !!!

Python是否应该阻止分配?我可能错过了一些东西。

任何想法?

My understanding was that Python strings are immutable.

I tried the following code:

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
# !!!

Shouldn’t Python have prevented the assignment? I am probably missing something.

Any idea?


回答 0

首先a指向字符串“ Dog”。然后,您将变量更改a为指向新的字符串“ Dog eats对待”。您实际上并未更改字符串“ Dog”。字符串是不可变的,变量可以指向它们想要的任何东西。

First a pointed to the string “Dog”. Then you changed the variable a to point at a new string “Dog eats treats”. You didn’t actually mutate the string “Dog”. Strings are immutable, variables can point at whatever they want.


回答 1

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

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.

The string objects themselves are immutable.

The variable, a, which points to the string, is mutable.

Consider:

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.

回答 2

变量a指向对象“ Dog”。最好将Python中的变量视为标签。您可以将标签移动到其他对象,这就是您更改为时的a = "dog"操作a = "dog eats treats"

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


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

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

因为字符串不支持项目分配,所以它们是不可变的。

The variable a is pointing at the object “Dog”. It’s best to think of the variable in Python as a tag. You can move the tag to different objects which is what you did when you changed a = "dog" to a = "dog eats treats".

However, immutability refers to the object, not the tag.


If you tried a[1] = 'z' to make "dog" into "dzg", you would get the error:

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

because strings don’t support item assignment, thus they are immutable.


回答 3

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

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

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

>> 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.

字符串是不可变的。我们如何证明呢?

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

我们得到

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

因此,我们无法使字符串发生变异。这意味着字符串是不可变的。

在重新分配中,您将变量更改为指向新位置本身。在这里,您没有改变字符串,而是改变了变量本身。以下是您正在做什么。

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

id重新分配之前和之后是不同的,因此这证明您实际上不是在变异,而是将变量指向新位置。这不是改变字符串,而是改变变量。

Something is mutable only when we are able to change the values held in the memory location without changing the memory location itself.

The trick is: If you find that the memory location before and after the change are the same, it is mutable.

For example, list is mutable. How?

>> 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.

A string is immutable. How do we prove it?

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

we get

TypeError: ‘str’ object does not support item assignment

So we failed mutating the string. It means a string is immutable.

In you reassigning, you change the variable to point to a new location itself. Here you have not mutated the string, but mutating the variable itself. The following is what you are doing.

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

id before and after reassignment is different, so it this proves that you are actually not mutating, but pointing the variable to new location. Which is not mutating that string, but mutating that variable.


回答 4

变量只是指向对象的标签。该对象是不可变的,但是如果需要,可以使标签指向完全不同的对象。

A variable is just a label pointing to an object. The object is immutable, but you can make the label point to a completely different object if you want to.


回答 5

考虑:

>>> 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>

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

Consider:

>>> 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>

Notice that the hex memory location did not change when I stored the same value in the variable twice. It did change when I stored a different value. The string is immutable. Not because of zealotry, but because you pay the performance penalty of creating a new object in memory. The variable a is just a label pointing to that memory address. It can be altered to point to anything.


回答 6

该语句a = a + " " + b + " " + c可以基于指针进行分解。

a + " "说给我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"驻留的内存部分,这就是不可变的意思。但是,我们可以更改指向该内存部分的标签(如果有)。

The statement a = a + " " + b + " " + c can be broken down based upon pointers.

a + " " says give me what a points to, which can’t be changed, and add " " to my current working set.

memory:

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

+ b says give me what b points to, which can’t be changed, and add it to current working set.

memory:

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

+ " " + c says add " " to the current set. Then give me what c points to, which can’t be changed, and add it to current working set. memory:

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

Finally, a = says set my pointer to point to the resulting set.

memory:

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

"Dog" is reclaimed, because no more pointers connect to it’s chunk of memory. We never modified the memory section "Dog" resided in, which is what is meant by immutable. However, we can change which labels, if any, point to that section of memory.


回答 7

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
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

回答 8

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

a = "dog"

数据"dog"被创建并放置在标签下a。标签可以更改,但内存中的内容不会更改。执行"dog"完该操作后,数据仍将存在于内存中(直到垃圾回收器将其删除)

a = "cat"

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

There is a difference between data and the label it is associated with. For example when you do

a = "dog"

the data "dog" is created and put under the label a. The label can change but what is in the memory won’t. The data "dog" will still exist in memory (until the garbage collector deletes it) after you do

a = "cat"

In your programm a now ^points to^ "cat" but the string "dog" hasn’t changed.


回答 9

Python字符串是不可变的。但是,a它不是字符串:它是具有字符串值的变量。您不能更改字符串,但是可以将变量的值更改为新字符串。

Python strings are immutable. However, a is not a string: it is a variable with a string value. You can’t mutate the string, but can change what value of the variable to a new string.


回答 10

变量可以指向它们想要的任何位置。如果执行以下操作,将引发错误:

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

Variables can point to anywhere they want.. An error will be thrown if you do the following:

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

回答 11

Python字符串对象是不可变的。例:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

在这个例子中,我们可以看到当我们在a中分配不同的值时,它不会被修改,而是创建了一个新对象。
而且无法修改。例:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

发生错误。

Python string objects are immutable. Example:

>>> a = 'tanim'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281536'
>>> a = 'ahmed'
>>> 'Address of a is:{}'.format(id(a))
'Address of a is:64281600'

In this example we can see that when we assign different value in a it doesn’t modify.A new object is created.
And it can’t be modified. Example:

  >>> a[0] = 'c'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    **TypeError**: 'str' object does not support item assignment

A error occurs.


回答 12

‘mutable’意味着我们可以更改字符串的内容,’immutable’意味着我们不能添加额外的字符串。

点击查看照片证明

‘mutable’ means that we can change the content of the string, ‘immutable’ means that we can’t add an extra string.

click for photo proof


回答 13

>>> a = 'dogs'

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

'dogs eat treats'

>>> print a

'dogs'

一成不变,不是吗?

变量更改部分已经讨论过。

>>> a = 'dogs'

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

'dogs eat treats'

>>> print a

'dogs'

Immutable, isn’t it?!

The variable change part has already been discussed.


回答 14

考虑这个示例

 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

我在博客中找到的更精确的解释之一是:

在Python中,(几乎)所有事物都是一个对象。在Python中我们通常称为“变量”的名称更恰当。同样,“赋值”实际上是名称与对象的绑定。每个绑定都有一个定义其可见性的范围,通常是名称起源的块。

例如:

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

当我们稍后说some_guy =’George’时,包含’Fred’的字符串对象不受影响。我们刚刚更改了名称some_guy的绑定。但是,我们没有更改’Fred’或’George’字符串对象。就我们而言,他们可能会无限期地生活下去。

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

Consider this addition to your example

 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

One of the more precise explanations I found in a blog is:

In Python, (almost) everything is an object. What we commonly refer to as “variables” in Python are more properly called names. Likewise, “assignment” is really the binding of a name to an object. Each binding has a scope that defines its visibility, usually the block in which the name originates.

Eg:

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

When we later say some_guy = ‘George’, the string object containing ‘Fred’ is unaffected. We’ve just changed the binding of the name some_guy. We haven’t, however, changed either the ‘Fred’ or ‘George’ string objects. As far as we’re concerned, they may live on indefinitely.

Link to blog: https://jeffknupp.com/blog/2012/11/13/is-python-callbyvalue-or-callbyreference-neither/


回答 15

在上述答案中添加更多内容。

id 变量的变化在重新分配时发生变化。

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

这意味着我们已经将变量突变a为指向新的字符串。现在有两个 string(str)对象:

'initial_string'id= 139982120425648

'new_string'id= 139982120425776

考虑下面的代码:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

现在,b指向'initial_string',并具有相同ida重新分配过的。

因此,'intial_string'尚未被突变。

Adding a bit more to above-mentioned answers.

id of a variable changes upon reassignment.

>>> a = 'initial_string'
>>> id(a)
139982120425648
>>> a = 'new_string'
>>> id(a)
139982120425776

Which means that we have mutated the variable a to point to a new string. Now there exist two string(str) objects:

'initial_string' with id = 139982120425648

and

'new_string' with id = 139982120425776

Consider the below code:

>>> b = 'intitial_string'
>>> id(b)
139982120425648

Now, b points to the 'initial_string' and has the same id as a had before reassignment.

Thus, the 'intial_string' has not been mutated.


回答 16

总结:

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中也不是错误,因为显然它不是不可变的。

Summarizing:

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

Not immutable:

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

Immutable:

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

This is an error in Python 3 because it is immutable. And not an error in Python 2 because clearly it is not immutable.


回答 17

内置函数id()以整数形式返回对象的标识。该整数通常对应于对象在内存中的位置。

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

最初,“ a”存储在139831803293008的存储位置中,因为如果您尝试修改和重新分配该字符串对象,则在python中该对象是不可变的,该引用将被删除,并将成为新存储位置的指针(139831803293120)。

The built-in function id() returns the identity of an object as an integer. This integer usually corresponds to the object’s location in memory.

\>>a='dog'
\>>print(id(a))

139831803293008

\>>a=a+'cat'
\>>print(id(a))

139831803293120

Initially, ‘a’ is stored in 139831803293008 memory location, as the string object is immutable in python if you try to modify and reassign the reference will be removed and will be a pointer to a new memory location(139831803293120).


回答 18

a = 'dog'
address = id(a)
print(id(a))

a = a + 'cat'
print(id(a))      #Address changes

import ctypes
ctypes.cast(address, ctypes.py_object).value    #value at old address is intact
a = 'dog'
address = id(a)
print(id(a))

a = a + 'cat'
print(id(a))      #Address changes

import ctypes
ctypes.cast(address, ctypes.py_object).value    #value at old address is intact

回答 19

此图像给出了答案。请阅读。

在此处输入图片说明

This image gives the answer. Please read it.

enter image description here


回答 20

我们只是串联两个字符串值。我们永远不会改变(a)的值。刚才(a)表示另一个具有“ dogdog”值的存储块。因为在后端,一个变量永远不会代表两个内存块。串联前(a)的值为“ dog”。但是在那之后(a)代表“ dogdog”,因为现在(a)在后端代表中。具有“ dogdog”值的块。而“狗”是代表。直到(b)代表“狗”,“ b”和“ dog”才算作垃圾值。

困惑在于我们用相同的变量名来表示后端的内存块(包含数据或信息)。

We r just concatenate the two string values. We never change the value of (a). Just now (a) represent another memory block that has “dogdog” value. Because in the backend, one variable never represent two memory blocks at same time. The value of (a) before concatenation was “dog”. But after that (a) represent the “dogdog”, because now (a) in backend rep. the block that has “dogdog” value. And “dog” is rep. by (b) and “dog” isn’t counted as garbage value until (b) represent the “dog”.

The confusion is we represent the memory blocks(that contain data or info.) in backend with same variable name.


回答 21

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

numpyarrayname[0] = "write once"

然后:

numpyarrayname.setflags(write=False)

要么

numpyarrayname.flags.writeable = False

You can make a numpy array immutable and use the first element:

numpyarrayname[0] = "write once"

then:

numpyarrayname.setflags(write=False)

or

numpyarrayname.flags.writeable = False

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。