【问题标题】:Dereferencing lists inside list in Python在 Python 中取消引用列表中的列表
【发布时间】:2013-05-13 21:37:19
【问题描述】:

当我以“通用”方式定义列表时:

>>>a=[[]]*3
>>>a
[[],[],[]]

然后尝试仅追加到外部列表的第二个元素:

>>>a[1].append([0,1])
>>>a
[[[0,1]], [[0,1]], [[0,1]]]

如上所示,它附加到外部列表的所有元素,可能是因为这些元素是对同一个列表而不是不同列表的引用(为什么它会这样工作?)。我如何才能以相同的“通用”方式实际创建一个列表,这样内部列表将是不同的列表而不仅仅是引用。谢谢。

【问题讨论】:

    标签: python list reference


    【解决方案1】:

    你是对的,它们都是对一个列表的引用。

    [[] for _ in range(3)]
    

    是创建独立空列表列表的常用方法。您可以在 Python 2.x 上使用 xrange,但如果长度实际上与您的示例中一样小,则不会有什么不同。

    不确定如何解释原因(原因是它是以这种方式实现的),但您可以看到这种行为已记录在案(至少顺便说一句)here:

    Operation       Result                              Notes
    s * n, n * s    n shallow copies of s concatenated  (2)
    

    这里的“浅”一词的确切含义是:元素是通过引用复制的。链接页面上的“注 2”也回答了您的问题。

    【讨论】:

    • 执行浅拷贝是一个不错的设计选择。进行深度复制会更加复杂和昂贵。这也是打破单例的一种简单方法:[True] * n 突然出现n 的不同实例 True(或任何用户定义的单例),这显然是你不想要的。
    • 谢谢。您提到如果长度很小我可以使用“范围”吗?在我的实际项目中,长度可以大到 10000。我还可以使用“范围”吗?我认为它仍然适用于数字,不是吗?
    • @Gregory 肯定会,但会创建一个包含 10000 个号码的列表并在此过程中立即删除。这可能不会占用太多内存,但可能比xrange 慢一点。您可以同时计时并查看。
    • @Gregory R - 对于 10000 个对象,差异微不足道。您可以使用 timeit 自己进行试验。调出python解释器,然后粘贴from timeit import timeit;timeit("[i for i in range(10000)]", number=10000)/10000。然后用 xrange 再试一次。在我的机器上大约是 100 微秒。
    • @tdelaney 您可以使用解释器的-m 选项:python -m timeit '[i for i in range(10000)]'timeit 模块将决定最佳重复次数并自动显示平均时间。无论如何,使用list(range(10000)) 的速度大约是列表理解的两倍。
    猜你喜欢
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 2013-03-30
    • 2014-12-14
    • 2021-01-10
    • 1970-01-01
    • 2011-03-10
    • 2018-05-18
    相关资源
    最近更新 更多