用现有对元素的引用来修改列表? [英] Modifying a list with existing references to elements?

查看:56
本文介绍了用现有对元素的引用来修改列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(如果您想跳过一些2 A.M. Python科学并开始追赶,我的问题将在最后总结)

(if you want to skip some 2 A.M. Python science and cut to the chase, my question is summed up at the very end)

请考虑以下内容:

1: animals = ['cat', 'cow', 'donkey', 'horse']  # we start with a list
2: animals_reference = animals  # make another reference and assign it to animals

3: cat = animals[0]  # refer cat to first element of animals
4: assert cat is animals[0]  # no copy occurred, still same object

5: animals[0] = animals[0].capitalize()  # change first element of list
6: assert cat is not animals[0]  # animals[0] now refers to another object
7: assert animals_reference is animals  # animals still points to the same object as before

我的理解是,Python列表的底层结构是C数组(有很多动态内容,但最终还是C数组).

My understanding was that the underlying structure of a Python list was a C array (with lots of dynamic stuff going on, but still, at the end of the day, a C array.)

这让我感到困惑:我们将cat设置为引用列表的第一个元素(3).在C语言中,将其引用为数组第一个元素的地址.

What's confusing me is this: we set cat to refer to the first element of the list (3). In C, that'd be referring it to the address of the first element of the array.

然后我们修改列表的第一个元素(5).

We then modify the first element of the list (5).

但是,这样做之后,猫不再引用该对象(6).但是,列表引用也没有改变,因为在(7)中我们看到它从开始就指向同一对象.

But after doing that, cat no longer refers to that object (6). However, the list reference hasn't changed either, since in (7) we see that it has pointed to the same object since the beginning.

这让我很困惑,因为它暗示即使没有重新分配猫,猫现在也指的是其他东西.

This is messing with my mind because it suggests that cat now refers to something else, even though it was never reassigned.

所以我进行了以下实验:

So I performed the following experiment:

cat = animals[0]  # refer cat to first element of animals
assert cat is animals[0]  # no copy occurred, still same object
print("id of cat:        {}".format(hex(id(cat))))
print("id of animals[0]: {}".format(hex(id(animals[0]))))
print("id of animals[]:  {}".format(hex(id(animals))))

print("capitalizing animals[0]...")
animals[0] = animals[0].capitalize()
print("-id of cat:        {}".format(hex(id(cat))))
print("-id of animals[0]: {}".format(hex(id(animals[0]))))
print("-id of animals[]:  {}".format(hex(id(animals))))

输出:

id of cat:         0xffdda580
id of animals[0]:  0xffdda580
id of animals[]:   0xffddc828
capitalizing animals[0]...
-id of cat:        0xffdda580  # stayed the same!
-id of animals[0]: 0xffe12d40  # changed!!
-id of animals[]:  0xffddc828

这使我相信Python列表不一定是内存的连续元素,对元素的更改将仅指向内存中的其他位置吗?我的意思是,数组第一个元素的地址在内存中早于数组本身的地址!

This has led me to believe that Python lists are not necessarily contiguous elements of memory and changes to an element will simply point to somewhere else in memory? I mean, the address of the first element of the array is earlier in memory than the address of the array itself!

列表使用的底层结构到底是什么,可以解释我所看到的内容?

What exactly is the underlying structure that lists use that explains what I saw?

推荐答案

这是一种思考方式:

1: animals = ['cat', 'cow', 'donkey', 'horse']  # we start with a list
2: animals_reference = animals  # make another reference and assign it to animals

3: cat = animals[0]  # refer cat to first element of animals

这不会使cat引用动物的第一要素",至少不是按照您的意思.它使cat引用动物的第一个元素所引用的内容.在这种情况下,即为字符串"cat".换句话说,表达式animals[0]本身就是对对象的引用.该对象是字符串cat.当您执行animals[0]时,您将获得表达式animals[0]所引用的对象.当您执行cat = animals[0]时,将cat设置为引用该对象.

This does not make cat refer to "the first element of animals", at least not in the way you seem to mean. It makes cat refer to whatever the first element of animals refers to. In this case, that is the string "cat". In other words, the expression animals[0] is itself a reference to an object. That object is the string cat. When you do animals[0], you get the object that the expression animals[0] refers to. When you do cat = animals[0], you set cat to refer to that object.

没有办法避免取消引用"值animals[0].也就是说,没有办法说给我animals[0]的指向性,以便当animals[0]开始指向其他内容时,我的新变量也将指向该其他内容".您只能获得animals[0]所指的内容,而不能获得其本身的引用性.

There is no way to avoid "dereferencing" the value animals[0]. That is, there is no way to say "give me the pointingness of animals[0] so that when animals[0] starts pointing at something else, my new variable will also point at that something else". You can only get what animals[0] refers to, not its referring-ness itself.

因此:

4: assert cat is animals[0]  # no copy occurred, still same object

5: animals[0] = animals[0].capitalize()  # change first element of list

在这里您更改animals[0]指向的内容.但是您将cat设置为animals[0]所指向的对象.因此,现在catanimals[0]指向不同的地方.字符串"cat"不变(这就是为什么is测试仍然显示值相同的原因);只是animals[0]不再指向该字符串,而是开始指向字符串"Cat".

Here you change what animals[0] points at. But you set cat to be what animals[0] used to point at. So now cat and animals[0] point at different things. The string "cat" did not change (which is why your is test still shows the values are the same); it's just that the animals[0] stopped pointing at that string and started pointing at the string "Cat" instead.

这篇关于用现有对元素的引用来修改列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆