(如果您想略过一些凌晨2点的Python科学知识,并追赶一下,我的问题将在最后总结)
考虑以下:
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数组。)
令我感到困惑的是:我们将
cat
设置为引用列表的第一个元素(3)。在C语言中,将其引用为数组第一个元素的地址。然后,我们修改列表的第一个元素(5)。
但是这样做之后,cat不再引用该对象(6)。但是,列表引用也没有改变,因为在(7)中我们看到它自开始以来就指向同一对象。
这让我很困惑,因为它暗示即使没有被重新分配,猫现在也指的是其他东西。
因此,我进行了以下实验:
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列表不一定是内存的连续元素,对元素的更改将仅指向内存中的其他位置吗?我的意思是,数组第一个元素的地址在内存中早于数组本身的地址!
清单使用的基本结构到底是什么,可以解释我所看到的?
最佳答案
这是一种思考方式:
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
设置为引用该对象。无法避免“取消引用”值
animals[0]
。也就是说,没有办法说“给我animals[0]
的指向性,以便当animals[0]
开始指向其他内容时,我的新变量也将指向其他内容”。您只能得到animals[0]
所指的内容,而不能获得其指称性本身。从而:
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]
所指向的对象。因此,现在cat
和animals[0]
指向不同的地方。字符串"cat"
不变(这就是为什么is
测试仍然显示值相同的原因);只是animals[0]
不再指向该字符串,而是开始指向字符串"Cat"
。关于python - 用现有的元素引用修改列表?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31488199/