[英]Why is reverse() on specific slice of a list not working?
我有一个列表, a = [0,1,2,3,4,5]
。
我正在尝试使用a[1:4].reverse()
反转切片a[1:4]
。 然而,值a
不会改变。 为什么会发生这种情况?
注意:我不想知道如何进行这项工作 - 而是,为什么会发生这种情况。
a[1:4]
创建一个新列表。 你叫reverse
这个新的名单上,而不是a
下面是a[1:4].reverse()
实际作用:
a
,所以a[1:4]
== [1, 2, 3]
[3, 2, 1]
list.reverse()
是一个修改原始列表的就地函数。
当您调用a[1:4]
, a[1:4]
只是从a
切片的值,并且没有容器(即变量)保存该变量。
就地修改功能是修改新创建的列表,即返回的切片列表。 但是,由于没有容器容纳它,也没有指向原来的a
,它会丢失。
参考文档在这里
您实际上是在处理a[1:4]
而不是a
。 由于您没有引用它,该列表将被丢弃。
看:
>>> a[1:4].reverse()
#==== No output ====
>>> d=a[1:4]
>>> d.reverse()
[3, 2, 1]
当列表未被引用时,它被丢弃。 但是当您将其分配给变量d
,您可以看到结果。
使用list
一个小监视器包装器(子类)可能最容易看到:
class ListWrapper(list):
def __setitem__(self, key, value):
print(f'__setitem__ was called on {id(self)}')
super(ListWrapper, self).__setitem__(key, value)
def __getitem__(self, item):
print(f'Get Item was called on {id(self)}')
n = ListWrapper(super(ListWrapper, self).__getitem__(item))
print(f'New id is {id(n)}')
return n
def reverse(self):
print(f'Reversed Called on {id(self)}')
super(ListWrapper, self).reverse()
本质上, ListWrapper
在此操作中使用的方法中包含了一些打印语句:
a = ListWrapper([0, 1, 2, 3, 4, 5])
print('ID of `a` is', id(a))
a[1:4].reverse()
print('ID of `a` is', id(a))
其输出为:
ID of `a` is 2002062741728
__getitem__ was called on 2002062741728
New id is 2002062745088 # Notice the ID is different
reverse called on 2002062745088 # Reverse is called on this new object
ID of `a` is 2002062741728 # The id of `a` has not changed
我们无法访问 ID 为2002062745088
的值,因为我们在任何地方都没有包含此信息的变量。
针对评论中的一个问题:“如果是这样,那么为什么 a[1:4] = [3,2,1] 会改变 a 的值?”
让我们也看看那个操作:
a = ListWrapper([0, 1, 2, 3, 4, 5])
print('ID of `a` is', id(a))
a[1:4] = [3, 2, 1]
print('ID of `a` is', id(a))
其输出为:
ID of `a` is 2760760102160
__setitem__ was called on 2760760102160
ID of `a` is 2760760102160
请注意, a
始终具有相同的id
。 并且前面示例中的函数都没有被调用( __getitem__
和reverse
)。 因此,更新发生在列表a
,其结果是可访问的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.