把代码精简了一下
我本以为输出结果会是个[[],[]],输出结果是个列表嵌套了两个列表,每个列表里又嵌套了 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 的
|