我有以下代码,为什么第一个不改变alist
而第二个可以改变它?
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item = 1
print(alist)
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item = item.append(10)
print(alist)
我有以下代码,为什么第一个不改变alist
而第二个可以改变它?
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item = 1
print(alist)
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item = item.append(10)
print(alist)
item
时,你只是改变了变量的引用,而不是它所指向的列表。alist = [[1,2], [3,4], [5,6]]
创建的列表。
考虑到这一点,让我们看看当执行你的第一个循环时会发生什么。
当你执行for item in alist
时,你要求解释器每次从列表中取出一个值,将其放入变量item
中并对其进行一些操作。例如,在第一个操作中,我们有了这个新模式:
item
中;相反,我们通过item
指向它。然后,我们执行item = 1
——但这意味着什么?这意味着我们将item
指向值1
,而不是指向子列表:
请注意,旧引用已丢失(即红色箭头),现在我们有了一个新引用。但我们只是改变了指向列表的变量 - 我们没有改变列表本身。item = 1
时,我们只是让变量指向另一个值,而不改变列表本身。
现在,当我们执行第二个循环时会发生什么?
第二个循环与第一个循环相同:我们让item
引用第一个子列表:
item.append()
。 append()
是一个方法,因此它可以更改调用它的对象的值。就像我们所说的那样,我们向item
指向的对象发送一个消息以附加值10。在这种情况下,操作不是在变量item
中进行的,而是直接在它所指的对象中进行的!因此,调用item.append()
的结果如下:
然而,我们不仅向列表附加一个值!我们还将赋值给item.append()
返回的值。这将切断item
与子列表之间的引用,但这里有一个问题:append()
返回None
。
None
值None
是一个表示基本上没有相关值可用的值。当函数返回None
时,它通常是在说:"我没有任何相关的东西可以给你。"append()
直接改变其列表,因此它不需要返回任何内容。
这很重要,因为你可能认为item
会指向附加的列表[1, 2, 10]
,对吗?不,现在它指向None
。所以,你会期望下面的代码...
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item = item.append(10)
print(item)
[1, 2, 10]
[3, 4, 10]
[5, 6, 10]
>>> alist = [[1,2], [3,4], [5,6]]
>>> for item in alist:
... item = item.append(10)
... print(item)
...
None
None
None
然而,正如我们所评论的那样,append()
方法改变了列表本身。因此,在赋值之后,item
变量是无用的,但最终的列表被修改了!
>>> print alist
[[1, 2, 10], [3, 4, 10], [5, 6, 10]]
item
。做法如下:>>> alist = [[1,2], [3,4], [5,6]]
>>> for item in alist:
... item.append(10)
... print item
...
[1, 2, 10]
[3, 4, 10]
[5, 6, 10]
item
仍将指向列表。
引用起初有些复杂,更不用说掌握了。然而,它们非常强大,如果您遵循示例等方式进行学习,就可以学会使用它们。您的示例有些复杂,因为这里发生了更多的事情。
Python Tutor可以帮助您理解正在发生的事情,因为它会以图形方式执行每个步骤。在那里检查您自己的代码运行!
item
绑定到列表alist
中的每个元素上,然后item
被重新绑定为整数1
。这不会改变列表的元素 - 它只是将名称item
重新绑定到int
对象1
。append()
进行了变异。 item
仍然绑定到子列表上,因此item.append()
会改变子列表。list.append()
并不返回列表本身,而是直接在原地修改列表。对于item = 1
,它的作用如预期一样。在for循环的其余部分中,item
现在是1
,而不是它最初的列表。它不会重新分配item
的值,因为这不是for循环的作用。然而,在你的第二个循环中,你现在正在赋值item = None
,因为append函数不返回任何值,但它会将项目附加到列表中。>>> L = [1, 2, 3]
>>> L.append(4)
>>> L
[1, 2, 3, 4]
10
添加到其中”。=
运算符不会对第二段代码进行任何更改,使用 .append
会导致 alist
发生变化。请在第二段代码的第三行中使用以下代码,您将看到相同的结果:
item.append(10)
item
通过item=1
指向另一个对象,因此alist
没有改变。在第二段代码中,您通过调用alist
的append
方法对其进行了更改。这是Python中的指针变量。
第一个例子:
for item in alist:
item = 1
for item in alist:
item = item.append(10)
每个项目都指向alist中的_each_item_,然后您将某些内容附加到与 _item 共享内存位置的项目中,结果alist中的 _item 的值会更改,alist也会更改。
所以你的第二个例子与以下内容完全相同:The for-loop makes assignments to the variables(s) in the target list. This overwrites all previous assignments to those variables including those made in the suite of the for-loop:
for i in range(10): print(i) i = 5 # this will not affect the for-loop # because i will be overwritten with the next # index in the range
alist = [[1,2], [3,4], [5,6]]
for item in alist:
item.append(10) # this statement modifies each item in alist
# , which is what item the variable "points to"
print(alist)
item
是每次迭代中的一个新变量。因此,在任何特定的迭代中为其赋值都是没有意义的,因为在下一次迭代的开始时,它的值将被下一个在 alist
中的项所覆盖。请注意保留html标签。当你写代码时
for item in alist:
liast
中创建每个项目的副本并将其存储在 item
变量中,并且你没有得到对 item
的引用。append
在原地更改列表并不返回任何值,这就是为什么你会发现值被更改为 None
(由于赋值 - 如果你删除它,你将得到正常的追加)。for each
块不会进行任何复制,即在每次迭代中,item
指向alist
的每个成员。 - SuB
for item in alist : alist[alist.index(item)]= 1
进行更改,那么item
是循环中的局部变量,在外部不起作用。 - dsgdfg