我有一些Python代码需要一个可迭代的(列表或元组或生成器表达式或任何其他可迭代的),并且需要将其复制到一个新列表中。
以下作品:
newlist = [x for x in olditerable]
但我想知道我是否可以这样做:
newlist = list(olditerable)
显然,如果 olditerable 是不是列表,它会按要求工作(制作副本)。 不太明显的是,当 olditerable is 列表时,它似乎也可以按要求工作(制作副本):
oldlist = [1,2,3]
newlist = list(oldlist)
assert newlist is not oldlist # so it didn't just return oldlist
oldlist.append("appended to oldlist")
newlist.append("appended to newlist")
print(f"oldlist is {oldlist}")
print(f"newlist is {newlist}")
输出进一步确认newlist不是oldlist:
oldlist is [1, 2, 3, 'appended to oldlist']
newlist is [1, 2, 3, 'appended to newlist']
这种复制行为有保证吗? 我无法以某种方式找到任何有关它的文档。
相比之下,
tuple(oldtuple)
确实不制作副本(当然,因为这样做很愚蠢,因为元组是不可变的):
oldtuple = (1,2,3)
newtuple = tuple(oldtuple)
assert newtuple is oldtuple
来自文档:
构造函数构建一个列表,其项目相同且位于相同的位置 作为 iterable 的项目排序。 iterable 可以是一个序列,一个 支持迭代的容器,或者迭代器对象。如果可迭代 已经是一个列表,创建并返回一个copy,类似于
。例如,iterable[:]
返回list('abc')
并且['a', 'b', 'c']
返回list( (1, 2, 3) )
。如果没有给出参数,则 构造函数创建一个新的空列表,[1, 2, 3]
。[]
list()
执行浅复制。这意味着虽然列表对象本身是新的,但它的元素不会被复制,而是被引用。如果您的列表包含可变对象(如其他列表或字典),则对新列表中的这些对象的修改将影响原始列表:
>>> oldlist = [[1, 2], [3, 4]]
>>> newlist = list(oldlist)
>>> newlist[1].append(5)
>>> oldlist
[[1, 2], [3, 4, 5]]
>>> newlist
[[1, 2], [3, 4, 5]]
>>> newlist.append(6)
>>> oldlist
[[1, 2], [3, 4, 5]]
>>> newlist
[[1, 2], [3, 4, 5], 6]