有人可以简要解释这两个 Python 操作在修改列表方面的区别吗?
demo = ["a", "b", "c"]
for d in demo:
d = ""
print demo
#output: ['a', 'b', 'c']
for c in range(len(demo)):
demo[c] = ""
print demo
#output: ['', '', '']
换句话说,为什么第一次迭代不修改列表?谢谢!
循环变量d
始终是对可迭代对象元素的引用。这个问题实际上并不是何时或何时不是参考的问题。它与您使用循环执行的分配操作有关。
在第一个示例中,您将对象中元素的原始引用与另一个空字符串的引用重新绑定。这意味着您实际上并没有对value做任何事情。您只需为符号分配一个新的引用。
在第二个示例中,您正在执行索引操作并为该索引处的值分配新引用。demo
保持相同的引用,并且您正在替换容器中的值。
该作业实际上相当于:demo.__setitem__(c, "")
a = 'foo'
id(a) # 4313267976
a = 'bar'
id(a) # 4313268016
l = ['foo']
id(l) # 4328132552
l[0] = 'bar'
id(l) # 4328132552
请注意在第一个示例中,对象 ID 发生了怎样的变化。它是对新对象的引用。在第二个中,我们索引列表并替换容器中的值,但列表仍然是同一个对象。
在第一个示例中,d
可以将变量视为列表中元素的副本。这样做时d = ""
,您实际上是在修改列表中任何内容的副本,这自然不会更改列表。
在第二个示例中,通过range(len(demo))
对列表中的元素进行操作和索引,您可以直接访问和更改列表中的元素。因此,doingdemo[c]
会修改列表。
如果您确实想从循环内部直接修改 Python 列表,则可以复制该列表并对其进行操作,或者最好使用列表推导式。
所以:
>>> demo = ["a", "b", "c"]
>>> test = ["" for item in demo]
>>> print test
["", "", ""]
>>> demo2 = [1, 5, 2, 4]
>>> test = [item for item in demo if item > 3]
>>> print test
[5, 4]
当你这样做时,d = <something>
你正在使变量d
引用<something>
. 这样您就可以d
像使用<something>
. 但是,如果您这样做d = <something else>
,则d
现在指向<something else>
和不再指向<something>
(=
符号用作赋值运算符)。在 的情况下demo[c] = <something else>
,您正在分配<something else>
给(c+1)th
列表中的项目。
但是,要注意的一件事是,如果该项目d
具有要调用的自修改方法,则可以执行
for d in demo:
d.<some method>()
因为列表demo
包含那些对象(或对对象的引用,我不记得了),因此如果修改了这些对象,列表也会被修改。