繁体   English   中英

为什么在列表的特定切片上的 reverse() 不起作用?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM