所以我正在用Python编写一个游戏,而我正在尝试解决的问题要求我将2D列表(即列表列表)转换为一维列表。我已经看到了几种方法,但我不知道是否有任何方法可以创建其中包含的任何对象的副本,或者只是新引用。老实说,Python标准库让我感到困惑,因为对象/序列是否被复制或者只是被引用填充并不总是很明显。
这些是关于我的特殊情况的假设;
谢谢!
答案 0 :(得分:7)
虽然我不能说出你可能看到的每一种方式,但由于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
,即对象本身。
答案 1 :(得分:1)
关于你关于副本/引用的问题,Python以不同的方式使用可变/不可变变量:对于不可变变量(int,float,string,tuples等),你将获得副本,可变(其他所有) - “引用”
关于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]
答案 2 :(得分:1)
python documentation中的这篇文章可能会帮助你理解python的作用:
没有人“拥有”一个物体;但是,你可以拥有一个引用 宾语。对象的引用计数现在定义为数量 拥有对它的引用。引用的所有者负责 在不再需要引用时调用Py_DECREF()。所有权 参考可以转移。处理有三种方法 拥有的引用:传递,存储或调用Py_DECREF()。 忘记处置自己的引用会造成内存泄漏。
现在,这指的是使用C代码中的python对象,但是,由于解释器正是这样做的,所以你可以理解如何在python中管理对象和引用。
“没有人拥有对象”,因此当您将项目放入列表时,此列表不复制该项目,它只拥有引用。实际上,它发生的是复制指针并增加引用计数(也可能减少被替换的其他对象)。
从python的角度来看,您无法访问对象,只能访问对象。
您可以放入变量的任何内容实际上是对对象的引用。
因此[1,2].append(3)
不会复制3,而只是复制参考。
如果要复制对象,则应使用copy
模块
或者,对于某些类型,使用对象作为参数调用类(例如int(1234)
创建“1234”的副本,即使python在小数组中存储从-5到256的整数和小字符串,这样做int(42)
不会复制“42”)
答案 3 :(得分:0)
您可以执行以下操作:
arr2d = [[1,2,3],[4,5,6],[7,8,9]]
arr1d = []
for x in arr2d:
arr1d.extend(x)
这不会创建副本,更改1d数组,它不会反映。对于将来的参考,如果您想确保不复制它,请导入copy
模块,并使用copy.deepcopy(array)
而不是array
,这样您就会安全。