当我偶然发现以下代码片段时,我只是在看functools.lru_cache的实现:
root = [] # root of the circular doubly linked list
root[:] = [root, root, None, None] # initialize by pointing to self
我熟悉圆形和双向链表。我也知道new_list = my_list[:]
创建了my_list的副本。
当寻找切片分配或圆形双向链表的其他实现时,我找不到关于此特定语法的任何更多信息。
问题:
some_list[:] =
some_iterable
是否有不同的常见用例(没有自我参考)?答案 0 :(得分:5)
在
root[:] = [root, root, None, None]
左手切片分配只是说root
的引用被重新使用来保存右部分的内容。
因此root
引用永远不会改变,是的,您可以在列表中引用自己(但不要尝试对它们进行递归展平:)。在这种情况下,表示形式将显示“列表上的递归”。
>>> root
[<Recursion on list with id=48987464>,
<Recursion on list with id=48987464>,
None,
None]
打印并显示省略号:
>>> print(root)
[[...], [...], None, None]
请注意,您不需要为此分配切片。有一些触发递归的简单方法:
>>> root = []
>>> root.append(root)
>>> root
[<Recursion on list with id=51459656>]
>>>
使用append
不会更改引用,众所周知,它只是对列表进行了变异,为其自身添加了引用。也许更容易理解。
答案 1 :(得分:2)
如果列表为l
,则将调用l[:] = items
的呼叫l.__setitem__(slice(None), items)
。清除后,此方法会将给定迭代器中的各个项目分配给列表。
你可以做
l.clear()
l.extend(items)
some_list[:] =
some_iterable (without the self reference)?
是否有不同的常见用例理论上,您可以将任何可迭代项放入列表中。
答案 2 :(得分:1)
只需查看反汇编的代码:
In [1]: def initializer():
...: root = [] # root of the circular doubly linked list
...: root[:] = [root, root, None, None]
...:
In [2]:
In [2]: import dis
In [3]: dis.dis(initializer)
2 0 BUILD_LIST 0
2 STORE_FAST 0 (root)
3 4 LOAD_FAST 0 (root)
6 LOAD_FAST 0 (root)
8 LOAD_CONST 0 (None)
10 LOAD_CONST 0 (None)
12 BUILD_LIST 4
14 LOAD_FAST 0 (root)
16 LOAD_CONST 0 (None)
18 LOAD_CONST 0 (None)
20 BUILD_SLICE 2
22 STORE_SUBSCR
24 LOAD_CONST 0 (None)
26 RETURN_VALUE
您要寻找的是STORE_SUBSCR
操作码,可用来实现以下目的:
mplements TOS1[TOS] = TOS2
由于do文档是就地操作的原因。而且,如果您想知道什么是就地操作,请按以下步骤定义文档:
就地操作类似于二进制操作,因为它们删除了TOS和TOS1,并将结果推回堆栈,但是当TOS1支持它时,就地完成了操作,结果TOS可能是(但是不必是原始的TOS1。
这将验证源代码中的嵌入式文档所说的内容:
通过指向自我进行初始化。
关于您的其他问题:
是否可以使用不同的语法来达到相同的结果?
是的,您可以按照其他答案中的说明清除并使用list.extend
属性设置列表项。或一一分配项目,也许哈哈
some_list [:]是否有其他常用用例= some_iterable(没有自我参考)?
这是一个非常模糊的问题,因为它是什么。以内射方式分配项目,这可能具有替换项目而无需重新创建引用等的好处。