python 按值列出而不是按引用列出[重复]

2024-12-17 08:30:00
admin
原创
116
摘要:问题描述:让我们举个例子a=['help', 'copyright', 'credits', 'license'] b=a b.append('XYZ') b ['help', 'copyright', 'credits', 'license', 'XYZ'] a ['help', 'copyright', ...

问题描述:

让我们举个例子

a=['help', 'copyright', 'credits', 'license']
b=a
b.append('XYZ')
b
['help', 'copyright', 'credits', 'license', 'XYZ']
a
['help', 'copyright', 'credits', 'license', 'XYZ']

我想在列表“b”中附加值,但列表“a”的值也发生了变化。

我想我不太明白为什么会这样(python 通过引用传递列表)。

我的问题是“我如何通过值传递它,以便附加“b”不会改变“a”中的值?”


解决方案 1:

在 Python 中,您无法按值传递任何东西。如果您想复制,您可以明确地这样做,如官方 Python FAQa中所述:

b = a[:]

解决方案 2:

要复制列表,您可以使用list(a)a[:]。在这两种情况下都会创建一个新对象。

但是,这两种方法对于可变对象集合有限制,因为内部对象会保持其引用不变:

>>> a = [[1,2],[3],[4]]

>>> b = a[:]
>>> c = list(a)

>>> c[0].append(9)

>>> a
[[1, 2, 9], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>> b
[[1, 2, 9], [3], [4]]
>>> 

如果你想要对象的完整副本,你需要copy.deepcopy

>>> from copy import deepcopy
>>> a = [[1,2],[3],[4]]

>>> b = a[:]
>>> c = deepcopy(a)

>>> c[0].append(9)

>>> a
[[1, 2], [3], [4]]
>>> b
[[1, 2], [3], [4]]
>>> c
[[1, 2, 9], [3], [4]]
>>> 

解决方案 3:

就性能而言,我最喜欢的答案是:

b.extend(a)

检查相关替代方案在性能方面的比较:

In [1]: import timeit

In [2]: timeit.timeit('b.extend(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[2]: 9.623248100280762

In [3]: timeit.timeit('b = a[:]', setup='b=[];a=range(0,10)', number=100000000)
Out[3]: 10.84756088256836

In [4]: timeit.timeit('b = list(a)', setup='b=[];a=range(0,10)', number=100000000)
Out[4]: 21.46313500404358

In [5]: timeit.timeit('b = [elem for elem in a]', setup='b=[];a=range(0,10)', number=100000000)
Out[5]: 66.99795293807983

In [6]: timeit.timeit('for elem in a: b.append(elem)', setup='b=[];a=range(0,10)', number=100000000)
Out[6]: 67.9775960445404

In [7]: timeit.timeit('b = deepcopy(a)', setup='from copy import deepcopy; b=[];a=range(0,10)', number=100000000)
Out[7]: 1216.1108016967773

解决方案 4:

此外,您还可以执行以下操作:

b = list(a)

这对于任何序列都有效,即使那些不支持索引器和切片的序列......

解决方案 5:

如果要复制一维列表,请使用

b = a[:]

但是,如果a是二维列表,则这不适合您。也就是说,中的任何更改a也将反映在中b。在这种情况下,使用

b = [[a[x][y] for y in range(len(a[0]))] for x in range(len(a))]

解决方案 6:

正如 phihag 在他的回答中提到的,

b = a[:]

适用于您的情况,因为切片列表会创建列表的新内存 ID(这意味着您不再引用内存中的同一个对象,并且对一个对象所做的更改不会反映在另一个对象中。)

但是,还有一个小问题。如果您的列表是多维的,例如列表中的列表,那么简单的切片无法解决这个问题。在更高维度(即原始列表中的列表)中所做的更改将在两者之间共享。

别担心,有解决办法。模块复制有一个巧妙的复制技术,可以解决这个问题。

from copy import deepcopy

b = deepcopy(a)

将会复制一个具有新内存 ID 的列表,无论它包含多少级列表!

解决方案 7:

当您这样做时,您只需创建指向ab = a的同一内存的另一个指针,这就是为什么当您附加到b时,a也会发生变化。

您需要创建a副本,方法如下:

b = a[:]

解决方案 8:

要创建列表的副本,请执行以下操作:

b = a[:]

解决方案 9:

我发现我们可以使用extend()来实现copy()的功能

a=['help', 'copyright', 'credits', 'license']
b = []
b.extend(a)
b.append("XYZ") 

解决方案 10:

我推荐以下解决方案:

b = []
b[:] = a

这会将所有元素从 a 复制到 b。复制将是值复制,而不是引用复制。

解决方案 11:

b = list(a)

请参阅http://henry.precheur.org/python/copy_list

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用