V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
zhoudaiyu
V2EX  ›  Python

学了 1 年 Python ,今天看了段代码觉得白学了,求教一下大家

  •  
  •   zhoudaiyu · 44 天前 · 3182 次点击
    这是一个创建于 44 天前的主题,其中的信息可能已经有所发展或是发生改变。

    把代码精简了一下

    image.png

    我本以为输出结果会是个[[],[]],输出结果是个列表嵌套了两个列表,每个列表里又嵌套了 2 个列表...

    image.png

    猜测是个递归,debug 一下确实是这样的

    image.png

    有几个问题:

    1 、这个为啥是个递归?
    2 、这个递归为什么没有爆栈?
    3 、修改了一下代码,为什么返回了(True, True)?

    image.png

    第 1 条附言  ·  43 天前
    感谢大家,基本理解了,我想问另外一个问题,就是这样写这个 root 列表会不会一直 gc 不掉?
    20 条回复    2021-03-06 01:14:51 +08:00
    chaosgoo
        1
    chaosgoo   44 天前
    1.root 里面放了两个 root 的引用
    2.root 里面只是存了两个地址而已
    3.自己和自己比较当然是 True
    THESDZ
        2
    THESDZ   44 天前
    实参,形参
    zhoudaiyu
        3
    zhoudaiyu   44 天前
    @zhoudaiyu

    大家忽略最后一个问题,脑残了
    aijam
        4
    aijam   44 天前
    相当于:
    root = []
    root.append(root)
    root.append(root)
    vicalloy
        5
    vicalloy   44 天前
    同楼上,就是一个递推的引用,换成 dict 是不是就好理解多了。
    >>> o = {}
    >>> o['o'] = o
    >>> o
    {'o': {...}}
    Vegetable
        6
    Vegetable   44 天前
    Circular reference detected

    给你化简一下吧
    root = []
    root.append(root)
    aijam
        7
    aijam   44 天前
    先理解下面什么意思,也就好理解了
    root = []
    root.append(root)
    nznd
        8
    nznd   44 天前
    >>> 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 可以用这个装作是原地算法(直接改这个值
    acmore
        9
    acmore   44 天前
    魔法就是自指广义表:
    root = []
    root.append(root)

    另外基本上所有语言都可以这么玩,不只是 Python
    RockShake
        10
    RockShake   44 天前
    自己引用了自己,死循环,print 无法打印出所有
    SystemLight
        11
    SystemLight   44 天前
    root[:]=[1,2]和 root=[1,2]两种写法有啥区别
    karloku
        12
    karloku   44 天前
    1.
    上面都回答了

    2.
    爆栈对应于堆栈. 变量引用不会建立堆栈, 自然没有爆栈问题.
    如果你准备用递归的函数来深层处理这个变量, 每次函数调用都会建立堆栈, 那基本就要爆了.
    karatsuba
        13
    karatsuba   44 天前
    这个不限于[], 即 root=[1], root=root.append(root),也会是[1, [...]]
    Jirajine
        14
    Jirajine   44 天前 via Android
    一切皆对象(的引用)
    因而所有变量都是引用类型(值类型可以看作是一种 inline 优化,因而可以看作引用类型)
    lizytalk
        15
    lizytalk   43 天前
    你想说 root[0] == root 和 root[0] is root 都是 True ? root=root 和 root is root 是 True 没什么可说的吧
    dayeye2006199
        16
    dayeye2006199   43 天前
    这个写法有什么实际用途吗?想学习一下魔法
    SjwNo1
        17
    SjwNo1   43 天前
    可变类型 地址引用
    no1xsyzy
        18
    no1xsyzy   43 天前
    数据自指不叫递归,因为它不会执行。

    @SystemLight 一个修改 list 内容,一个修改 locals() 绑定。
    cassidyhere
        19
    cassidyhere   43 天前
    标准库 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
    lithbitren
        20
    lithbitren   42 天前
    只要引用名归零或者作用域销毁,循环引用也是可以被 GC 的
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2011 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:29 · PVG 18:29 · LAX 03:29 · JFK 06:29
    ♥ Do have faith in what you're doing.