把代码精简了一下
我本以为输出结果会是个[[],[]],输出结果是个列表嵌套了两个列表,每个列表里又嵌套了 2 个列表...
猜测是个递归,debug 一下确实是这样的
有几个问题:
1 、这个为啥是个递归?
2 、这个递归为什么没有爆栈?
3 、修改了一下代码,为什么返回了(True, True)?
![]() | 1 chaosgoo 2021-03-04 15:11:12 +08:00 1.root 里面放了两个 root 的引用 2.root 里面只是存了两个地址而已 3.自己和自己比较当然是 True |
2 THESDZ 2021-03-04 15:14:03 +08:00 实参,形参 |
![]() | 4 aijam 2021-03-04 15:16:16 +08:00 相当于: root = [] root.append(root) root.append(root) |
![]() | 5 vicalloy 2021-03-04 15:17:22 +08:00 同楼上,就是一个递推的引用,换成 dict 是不是就好理解多了。 >>> o = {} >>> o['o'] = o >>> o {'o': {...}} |
![]() | 6 Vegetable 2021-03-04 15:17:34 +08:00 Circular reference detected 给你化简一下吧 root = [] root.append(root) |
![]() | 7 aijam 2021-03-04 15:17:49 +08:00 先理解下面什么意思,也就好理解了 root = [] root.append(root) |
8 nznd 2021-03-04 15:22:27 +08:00 >>> root=[] >>> id(root) 2296081934592 >>> id(root[:]) 2296081935040 >>> root[:]=[root,root] >>> id(root) 2296081934592 >>> id(root[:]) 2296081935040 >>> id(root[0]) 2296081934592 >>> id(root[1]) 2296081934592 简单来说 就是 root[0] 和 root[1] 都指向了 root,root[:]是 root 的一个指针(类似的概念 忘了叫啥了,刷 leetcode 可以用这个装作是原地算法(直接改这个值 |
9 acmore 2021-03-04 15:33:35 +08:00 魔法就是自指广义表: root = [] root.append(root) 另外基本上所有语言都可以这么玩,不只是 Python |
![]() | 10 RockShake 2021-03-04 15:35:41 +08:00 自己引用了自己,死循环,print 无法打印出所有 |
![]() | 11 SystemLight 2021-03-04 15:45:25 +08:00 root[:]=[1,2]和 root=[1,2]两种写法有啥区别 |
![]() | 12 karloku 2021-03-04 15:48:19 +08:00 1. 上面都回答了 2. 爆栈对应于堆栈. 变量引用不会建立堆栈, 自然没有爆栈问题. 如果你准备用递归的函数来深层处理这个变量, 每次函数调用都会建立堆栈, 那基本就要爆了. |
![]() | 13 karatsuba 2021-03-04 18:21:28 +08:00 这个不限于[], 即 root=[1], root=root.append(root),也会是[1, [...]] |
14 Jirajine 2021-03-04 18:29:31 +08:00 via Android 一切皆对象(的引用) 因而所有变量都是引用类型(值类型可以看作是一种 inline 优化,因而可以看作引用类型) |
![]() | 15 lizytalk 2021-03-04 18:47:49 +08:00 你想说 root[0] == root 和 root[0] is root 都是 True ? root=root 和 root is root 是 True 没什么可说的吧 |
16 dayeye2006199 2021-03-05 05:33:50 +08:00 这个写法有什么实际用途吗?想学习一下魔法 |
![]() | 17 SjwNo1 2021-03-05 09:29:51 +08:00 可变类型 地址引用 |
![]() | 18 no1xsyzy 2021-03-05 10:19:45 +08:00 |
19 cassidyhere 2021-03-05 10:35:32 +08:00 标准库 functools.lru_cache 把它当双向链表用 摘部分代码: PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 # names for the link fields root = [] # root of the circular doubly linked list root[:] = [root, root, None, None] # initialize by pointing to self # Use the old root to store the new key and result. oldroot = root oldroot[KEY] = key oldroot[RESULT] = result # Empty the oldest link and make it the new root. # Keep a reference to the old key and old result to # prevent their ref counts from going to zero during the # update. That will prevent potentially arbitrary object # clean-up code (i.e. __del__) from running while we're # still adjusting the links. root = oldroot[NEXT] oldkey = root[KEY] oldresult = root[RESULT] root[KEY] = root[RESULT] = None |
![]() | 20 lithbitren 2021-03-06 01:14:51 +08:00 只要引用名归零或者作用域销毁,循环引用也是可以被 GC 的 |