简体   繁体   English

为什么在Python中发生这种情况? 是否与列表可变性有关?

[英]Why is this happening in Python ? Is it do with list mutability?

Please don't be harsh if my question is very simple or obvious. 如果我的问题非常简单或明显,请不要苛刻。 Am a Python newbie, so just started out. 我是一个Python新手,所以刚刚开始。

Actually this was a piece of code I came across on this Stack Overflow only but could not find an answer for why this is happening, so decided to ask it myself. 实际上这只是我在Stack Overflow上遇到的一段代码,但是找不到为什么会发生这种情况的答案,所以决定自己问一下。

I wrote the below two programs : 我写了以下两个程序:

1) 1)

x=[1,2,3]
y=x
print x
y=y+[3,2,1]
print x

Output: 输出:

[1,2,3]
[1,2,3]

2) 2)

x=[1,2,3]
y=x
print x
y+=[3,2,1]
print x

Output: 输出:

[1,2,3]
[1,2,3,3,2,1]

I can't understand why the two outputs are different in this case ? 我不明白为什么这两种输出在这种情况下是不同的? is y=y+(something) not the same as y+=(something) y=y+(something)y+=(something) y=y+(something)不一样

what is it that I am missing here ? 我在这里失踪的是什么?

Thanks a lot for helping me out on this 非常感谢帮助我解决这个问题

This has nothing to do with mutability. 这与可变性无关。 It has to do with list objects and references to it. 它与列表对象和对它的引用有关。

When you do: 当你这样做时:

y=x

You are essentially making y refer to the same list that x is referring to. 你实际上是在y指代x所指的相同列表。

Now, 现在,

y=y+[3,2,1]
  ^-------^  - Create a **new** List is that is equal to concatenation of `y` and [1,2,3]
^---^        - Bind variable `y` to this **new** list.
             - The original list which `x` refered to -- is still *intact*

Again, 再次,

y+=[3,2,1]
 ^-------^   - Append [1,2,3] **in-place**. 
             - Since even `x` is pointing to the same list, it gets modified.

y = y+something will replace the contents of y , while y+=something will modify the list in-place. y = y+something会替换y的内容,而y+=something会在原位修改列表。

TL;DR; TL; DR; Code explanation: 代码说明:

>>> x = [1, 2]
>>> y = x
>>> id(y) == id(x)
True
>>> y += [3]
>>> id(y) == id(x)
True
>>> y = y + [3]
>>> id(y) == id(x)
False

Here's a little explanation of what's going on in your code.\\ 这里有一些关于代码中发生了什么的解释。

First code 第一个代码

You declared x: 你声明了x:

x=[1,2,3]

Then you point y to the value of x : 然后你点y到的值x

y=x

After that, here's the tricky part: 在那之后,这是棘手的部分:

y=y+[3,2,1]

This creates a new y variable, replacing the old one. 这将创建一个新的y变量,替换旧的变量。 y is no longer related to x . y不再与x相关。 Now, x has it's own place in memory, and y has a separate one 现在, x在内存中有自己的位置, y有一个独立的位置

Second code 第二个代码

Declare x : 声明x

x=[1,2,3]

Points y to the value of x : y指向x的值:

y=x

And lastly: 最后:

y+=[3,2,1]

This modifies the list pointed by y in-place. 这会修改y就地指向的列表。 In other words, you're modifying x as well: 换句话说,你也在修改x

If this isn't clear enough, just comment:) 如果这还不够清楚,只需评论:)

Hope this helps! 希望这可以帮助!

After the line 行后

y = x

Both x and y point to the same object. xy指向同一个对象。 In way that operators are overloadable in Python: 运算符在Python中是可重载的:

y += [3, 2, 1]

Is calling function 正在呼叫功能

y.__iadd__([3, 2, 1])

Which in turn adds the elements of [3, 2, 1] to a list pointed by y - which happens to be the same list pointed by x . 这又将[3, 2, 1] 3,2,1]的元素添加到y指向的列表中 - 恰好是x指向的相同列表。 On the other hand: 另一方面:

y = y + [3, 2, 1]

Is the same as: 是相同的:

y = y.__add__([3, 2, 1])

Which, in turn, creates a new list containing combination of both and assign it to y . 反过来,它创建一个包含两者组合的新列表,并将其分配给y After it y and x points to different objects and the one pointed by x is not modified. 后它yx点到不同的对象和所述一个由指向x不被修改。

No, it's not the same. 不,这不一样。 In fact this was one of the reasons why it took a long time for Python to get += , in the beginning people thought it would be too confusing to add. 事实上,这是为什么Python需要花费很长时间来获得+=的原因之一,一开始人们认为添加它会让人感到困惑。

y = y + [3, 2, 1]

Rebinds y to a new value, the one that is the result of the expression y + [3, 2, 1]. 将y重新绑定到一个新值,即表达式y + [3,2,1]的结果。

But

y += [3, 2, 1]

changes y, if it currently refers to something that can be changed. 更改 y,如果它当前指的是可以更改的内容。 And lists can. 并且列表可以。

Since the list that y refers to is changed, and x refers to the same list, printing x also shows the new value. 由于y引用的列表已更改,并且x指的是同一列表,因此打印x也会显示新值。

If y were immutable (like a tuple), then it doesn't work that way: 如果y是不可变的(如元组),那么它不会那样工作:

x = y = (1, 2, 3)
y += (3, 2, 1)
print(x)  # prints (1, 2, 3)
print(y)  # prints (1, 2, 3, 3, 2, 1)

The reason is that in the case of mutable objects, it's more likely that changing the object is what you actually want, so they made it work that way. 原因在于,在可变对象的情况下,更改对象更有可能是您真正想要的,因此他们使其以这种方式工作。 Immutable object can't work that way, so they don't. 不可变对象不能以这种方式工作,所以他们不这样做。

In python every time you use the operator = you "delete" the old version and create a new one. 在python中每次使用operator =你“删除”旧版本并创建一个新版本。

Thus y = y + something will create a new variable of y that isn't the same as the old y. 因此y = y + something会创建一个y的新变量,它与旧的y不同。

While y+=something will add something to the current value in y. 虽然y+=something会在y中为当前值添加一些东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM