请教python通过切片为列表赋值是怎么在内存上体现的

2024-12-02 11:16:00
推荐回答(5个)
回答1:

这个很好理解,slice切片就是将shoplist内不特定的一组序列存到另一块开辟的内存里。虽然你是将shoplist的全部转存到mylist但,它只是slice中的一种特列。第一次mylist = shoplist
相当于C语言中的内存指针指向同一片内存区域中。第二次mylist = shoplist和C语言中的内存复制是一个道理。

另一位朋友说是浅拷贝,我有不同看法,应该是深拷贝。slice在内存中重新申请了一片区域,是再一次重新建立的数据。改变原有元素的值,并不会改变新变量里的值。
可以通过对元素重新赋值,打印两变量,可得出结论。

回答2:

  我也是初学者,通过我看的书上的一个例子的理解,通过切片操作符获取序列的一个切片,就是一个拷贝,当你改变这个新序列中的值时,不会对原来的序列有影响,也就是说他们不是同一个内存。
  而直接复制,就像你理解的那样,指向了原来序列的地址,这时对新的序列进行操作就会影响到原来序列中的值。
  下面是个例子

  shoplist = ["apple","mango","carrot","banana"]
  mylist = shoplist
  del shoplist[0]#删除第一个对象
  print "shoplist is", shoplist
  print "mylist is", mylist
#两个序列值同样变化

  mylist = shoplist[:] #全部拷贝的切片
  del shoplist[0]
  print "shoplist is", shoplist
  print "mylist is", mylist
  #两个序列值不同

  del mylist[1]
  print "shoplist is", shoplist
  print "mylist is", mylist
#shoplist 未受影响

  输出结果:
shoplist is ['mango', 'carrot', 'banana']
  mylist is ['mango', 'carrot', 'banana']
  shoplist is ['carrot', 'banana']
  mylist is ['mango', 'carrot', 'banana']
  shoplist is ['carrot', 'banana']
  mylist is ['mango', 'banana']
  

回答3:

>>> shoplist = ['apple', 'mango', 'carrot', 'banana']
>>> id(shoplist)
27138648
这三句相当于吹了一个汽球,系了根线,将这根线交给A;
……
>>> mylist = shoplist
>>> id(mylist)
27138648
这三句相当于,将刚才的汽球又系了根线,并交给B;此时A和B虽然都牵了根线,但汽球是同一个;
……
mylist = shoplist[:]
>>> id(mylist)
27138728
这三句,相当于重新吹了一个和刚才一模一样的汽球,系了根线,并交到C的手上;

综上所述,汽球是实际对象,id是内存地址的映射;也就是说一个对象可以有多个引用;此时顺着B手上的线把汽球戳破了,A线上的汽球也就不存在了;
换言之列表直接赋值,只是多了一个引用;slice()方法会将范围内列表复制一个出来,并分本新地址变量,与原来的无关了;这在官方文档的介绍中有说明。

回答4:

python中的变量都是对象的引用,mylist=shoplist只是给了同一个对象不同的名字,实际上指向的是同一个对象。
切片是对象的浅拷贝,是在空闲内存中创建了一个新的对象,注意是浅拷贝,创建了一个新的列表对象,但列表中指向的元素还是同一个对象

回答5:

如果你学过C语言的话,可以把python中每个非原始类型数据理解为一个指针指向的对象。所以list里面所有的元素包括list本身都是对象。对象拷贝通常都是指针拷贝,也就是说浅拷贝。