展开Python列表而不创建任何对象的副本?

2024-05-15 12:06:35 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我用Python编写了一个游戏,我试图解决的一个问题是,我需要将一个2D列表(即列表列表列表)转换为1D列表。我已经看到了几种方法来实现这一点,但我不知道其中是否有任何一种方法创建了包含在其中的任何对象的副本,还是仅仅创建了新的引用。老实说,python标准库让我很困惑,因为并不总是很明显对象/序列是被复制的还是仅仅填充了引用。在

这些是关于我的特殊情况的假设

  • 我们可以假设我的二维列表,如果用矩阵表示,是完全矩形的。在
  • 如果我能找到一个上述假设不成立的解决方案,那就太好了,但目前还不需要。在
  • 不用担心3D+列表。在

谢谢!在


Tags: 对象方法游戏列表标准副本情况序列
3条回答

关于复制/引用的问题,Python以不同的方式处理可变/不可变变量:对于不可变变量(int、float、string、tuples等),您将获得副本;对于可变变量(其他所有变量)—“references”。在

关于python列表的扁平化:请看itertools模块。你可以这样做:

>>> from itertools import chain
>>> chain(*[[1,2,3], [4,5,6], [7,8,9]])
<itertools.chain object at 0x104ff5110>
>>> list(_)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

虽然我不能说出您可能看到的每一种方式,但由于Python的对象语义,一般不会进行复制。在

>>> a = [[1,2.3,'3', object()], [None, [2,3], 4j]]
>>> b = [v for row in a for v in row]
>>> a
[[1, 2.3, '3', <object object at 0x1002af090>], [None, [2, 3], 4j]]
>>> b
[1, 2.3, '3', <object object at 0x1002af090>, None, [2, 3], 4j]
>>> [id(obj) for row in a for obj in row]
[4298185464, 4298195480, 4299558664, 4297781392, 4296523616, 4299692656, 4297773296]
>>> [id(obj) for obj in b]
[4298185464, 4298195480, 4299558664, 4297781392, 4296523616, 4299692656, 4297773296]

这个v并不意味着“某个新对象等于v”,它只是意味着v,即对象本身。在

可能这篇来自python documentation的文章可以帮助您理解python的作用:

Nobody “owns” an object; however, you can own a reference to an object. An object’s reference count is now defined as the number of owned references to it. The owner of a reference is responsible for calling Py_DECREF() when the reference is no longer needed. Ownership of a reference can be transferred. There are three ways to dispose of an owned reference: pass it on, store it, or call Py_DECREF(). Forgetting to dispose of an owned reference creates a memory leak.

现在,这指的是从C代码中使用python对象,但是,由于解释器正是这样做的,所以您可以理解在python中如何管理对象和引用。在

“没有人拥有一个对象”,所以当你把一个项目放到一个列表中时,这个列表并不复制这个项目,它只是拥有一个引用。实际上,它复制一个指针并增加引用计数(也可能减少被替换的另一个对象)。在

从python的角度来看,不能访问对象,只能访问对象的引用。 任何可以放入变量中的内容实际上都是对对象的引用。 因此,[1,2].append(3)不会复制3,而只是复制引用。在

如果您想复制一个对象,那么您应该使用copy模块 或者,对于某些类型,使用对象作为参数调用类(例如,int(1234)创建“1234”的副本,即使python将-5到256的整数和小字符串存储在一个小数组中,因此int(42)不会复制“42”)

相关问题 更多 >