关于python中的迭代器

2024-05-08 13:50:33 发布

您现在位置:Python中文网/ 问答频道 /正文

如果我有以下列表:

a = [1, 2, 3]

我运行以下代码:

^{pr2}$

似乎这并没有改变列表a。在

但是,如果我执行以下操作:

for i in range(0, len(a)):
  a[i] += 1

这将修改“a”的内容。在

所以我猜x和{}以不同的方式引用a的元素。到底是什么造成了这种差异?它们是如何引用a的元素的?在


Tags: 代码in元素内容列表forlen方式
3条回答

这里重要的概念是引用。在Python中,变量是对内存中某个位置的对象的引用。让我们用箭头→来表示引用。变量→对象。变量在左边,对象在右边。在

数组可以可视化为三个变量,它们引用三个整数对象。在

a[0] → int(1)
a[1] → int(2)
a[2] → int(3)

现在,整数对象是不可变的。他们不能改变。当你改变一个整型变量时,你并没有改变变量所指的对象。不能,因为int是不可变的。你能做的就是让变量引用一个不同的对象。在

直接更新

让我们先看看第二个循环,因为它更简单。如果直接更新数组会怎么样?在

^{pr2}$

首先让我们展开循环:

a[0] += 1
a[1] += 1
a[2] += 1

对于整数,a[0] += 1相当于a[0] = a[0] + 1。首先,Python计算a[0] + 1并得到结果int(2)。然后它将a[0]改为引用int(2)。第二条和第三条语句的计算方式类似。在

^{4}$

间接更新

我称之为“间接”的更新呢?在

for x in a:
  x += 1

展开循环会产生一系列等效的语句:

x = a[0]
x += 1
x = a[1]
x += 1
x = a[2]
x += 1

每一步都会发生什么,为什么数组没有改变?在

x = a[0]

这使得x引用a[0]引用的任何对象。a[0]x引用相同的int(1)对象,但是x没有直接连接到a[0]。它引用a[0]所指的任何内容,而不是{}本身。在

x += 1

这将改变x所指的内容。它对a[0]没有影响。在

第二次和第三次作业也是如此。结果是x是不断变化的,而{}的元素仅仅是从中读取而从不被修改。因此,当循环终止时a不变。在

a = [1, 2, 3]  # a[0] → int(1)
               # a[1] → int(2)
               # a[2] → int(3)

x = a[0]       # x → int(1)
x += 1         # x → int(2)
x = a[1]       # x → int(2)
x += 1         # x → int(3)
x = a[2]       # x → int(3)
x += 1         # x → int(4)

迭代列表时,依次生成每个元素。然而,有不同种类的物体。可变不可变。当你做如下事情时:

a += 1

对于一个不可变的对象,它大致可以翻译为:

^{pr2}$

现在在本例中,通过a获取对象引用,向其添加1以创建一个新对象。然后为这个新对象指定名称a。请注意,如果我们在迭代时这样做,我们根本不会接触列表——我们只会不断地创建新对象并将它们分配给名称a。在

对于可变的对象,这是不同的。然后a += 1实际上改变了对象的位置。因此,列表将看到更改,因为它所持有的对象已更改(更改)。(对于不可变对象,列表中包含的对象没有更改,因为它不能更改)。有关详细信息,请参见this question。在

这也让我们更清楚地了解了当您按索引迭代时发生了什么。你构造了一个新的整数,然后把它放在列表中(忘记之前在那个槽里的东西)。在

当你说

for x in [1,2,3]:
    x+=1

你的意思是,暂时将x保存为变量,然后在临时保存中添加一个。当你进入下一个迭代时,垃圾管理员会销毁这个变量,因为它是临时的。x不在名单上。它是列表中那个位置的值。在

编辑:当我说它被删除时,我没有说清楚我的话。每次循环中,x都会被另一个值替换,所以之前发生的事情就消失了(除非你用它做了其他事情)。但是,对于您正在使用的操作,您不会更改列表中任何元素的值。我对混乱很不利。在

当你用另一种方式做的时候

^{pr2}$

然后你在谈论列表的值。x是变量的索引,因此可以在该点更改列表值的值。在

相关问题 更多 >

    热门问题