2024-05-08 13:50:33 发布
网友
如果我有以下列表:
a = [1, 2, 3]
我运行以下代码:
似乎这并没有改变列表a。在
a
但是,如果我执行以下操作:
for i in range(0, len(a)): a[i] += 1
这将修改“a”的内容。在
所以我猜x和{}以不同的方式引用a的元素。到底是什么造成了这种差异?它们是如何引用a的元素的?在
x
这里重要的概念是引用。在Python中,变量是对内存中某个位置的对象的引用。让我们用箭头→来表示引用。变量→对象。变量在左边,对象在右边。在
数组可以可视化为三个变量,它们引用三个整数对象。在
a[0] → int(1) a[1] → int(2) a[2] → int(3)
现在,整数对象是不可变的。他们不能改变。当你改变一个整型变量时,你并没有改变变量所指的对象。不能,因为int是不可变的。你能做的就是让变量引用一个不同的对象。在
int
让我们先看看第二个循环,因为它更简单。如果直接更新数组会怎么样?在
首先让我们展开循环:
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)。第二条和第三条语句的计算方式类似。在
a[0] += 1
a[0] = a[0] + 1
a[0] + 1
int(2)
a[0]
我称之为“间接”的更新呢?在
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]所指的任何内容,而不是{}本身。在
int(1)
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
对于一个不可变的对象,它大致可以翻译为:
现在在本例中,通过a获取对象引用,向其添加1以创建一个新对象。然后为这个新对象指定名称a。请注意,如果我们在迭代时这样做,我们根本不会接触列表——我们只会不断地创建新对象并将它们分配给名称a。在
对于可变的对象,这是不同的。然后a += 1实际上改变了对象的位置。因此,列表将看到更改,因为它所持有的对象已更改(更改)。(对于不可变对象,列表中包含的对象没有更改,因为它不能更改)。有关详细信息,请参见this question。在
这也让我们更清楚地了解了当您按索引迭代时发生了什么。你构造了一个新的整数,然后把它放在列表中(忘记之前在那个槽里的东西)。在
当你说
for x in [1,2,3]: x+=1
你的意思是,暂时将x保存为变量,然后在临时保存中添加一个。当你进入下一个迭代时,垃圾管理员会销毁这个变量,因为它是临时的。x不在名单上。它是列表中那个位置的值。在
编辑:当我说它被删除时,我没有说清楚我的话。每次循环中,x都会被另一个值替换,所以之前发生的事情就消失了(除非你用它做了其他事情)。但是,对于您正在使用的操作,您不会更改列表中任何元素的值。我对混乱很不利。在
当你用另一种方式做的时候
然后你在谈论列表的值。x是变量的索引,因此可以在该点更改列表值的值。在
这里重要的概念是引用。在Python中,变量是对内存中某个位置的对象的引用。让我们用箭头→来表示引用。变量→对象。变量在左边,对象在右边。在
数组可以可视化为三个变量,它们引用三个整数对象。在
现在,整数对象是不可变的。他们不能改变。当你改变一个整型变量时,你并没有改变变量所指的对象。不能,因为
int
是不可变的。你能做的就是让变量引用一个不同的对象。在直接更新
让我们先看看第二个循环,因为它更简单。如果直接更新数组会怎么样?在
^{pr2}$首先让我们展开循环:
对于整数,
^{4}$a[0] += 1
相当于a[0] = a[0] + 1
。首先,Python计算a[0] + 1
并得到结果int(2)
。然后它将a[0]
改为引用int(2)
。第二条和第三条语句的计算方式类似。在间接更新
我称之为“间接”的更新呢?在
展开循环会产生一系列等效的语句:
每一步都会发生什么,为什么数组没有改变?在
这使得}本身。在
x
引用a[0]
引用的任何对象。a[0]
和x
引用相同的int(1)
对象,但是x
没有直接连接到a[0]
。它引用a[0]
所指的任何内容,而不是{这将改变
x
所指的内容。它对a[0]
没有影响。在第二次和第三次作业也是如此。结果是}的元素仅仅是从中读取而从不被修改。因此,当循环终止时
x
是不断变化的,而{a
不变。在迭代列表时,依次生成每个元素。然而,有不同种类的物体。可变和不可变。当你做如下事情时:
对于一个不可变的对象,它大致可以翻译为:
^{pr2}$现在在本例中,通过
a
获取对象引用,向其添加1以创建一个新对象。然后为这个新对象指定名称a
。请注意,如果我们在迭代时这样做,我们根本不会接触列表——我们只会不断地创建新对象并将它们分配给名称a
。在对于可变的对象,这是不同的。然后
a += 1
实际上改变了对象的位置。因此,列表将看到更改,因为它所持有的对象已更改(更改)。(对于不可变对象,列表中包含的对象没有更改,因为它不能更改)。有关详细信息,请参见this question。在这也让我们更清楚地了解了当您按索引迭代时发生了什么。你构造了一个新的整数,然后把它放在列表中(忘记之前在那个槽里的东西)。在
当你说
你的意思是,暂时将x保存为变量,然后在临时保存中添加一个。当你进入下一个迭代时,垃圾管理员会销毁这个变量,因为它是临时的。x不在名单上。它是列表中那个位置的值。在
编辑:当我说它被删除时,我没有说清楚我的话。每次循环中,x都会被另一个值替换,所以之前发生的事情就消失了(除非你用它做了其他事情)。但是,对于您正在使用的操作,您不会更改列表中任何元素的值。我对混乱很不利。在
当你用另一种方式做的时候
^{pr2}$然后你在谈论列表的值。x是变量的索引,因此可以在该点更改列表值的值。在
相关问题 更多 >
编程相关推荐