Python多变量连续赋值与深浅拷贝机制详解

Noah
Noah
发布时间:2026-10-15| 4人浏览过
原创

本文解析Python中多变量连续赋值(如a=b=c=1)的原理,指出其本质是引用同一内存地址。重点区分浅拷贝与深拷贝:浅拷贝仅复制外层对象,嵌套对象仍共享引用;深拷贝则递归复制所有层级,生成完全独立的新对象。通过代码示例展示修改不同拷贝方式下列表对原数据的影响,帮助开发者避免常见的引用陷阱。

首先观察以下代码片段。


self.batch_size = batch_size = 128

乍看之下可能令人困惑,但深入分析后不难发现其逻辑的合理性。

在Python开发中,若需同时声明多个变量并赋予相同的初始值,可采用连续赋值的方式实现。


a=b=c=1

然而,此处存在一个关键注意点:当赋值的对象为列表或字典等可变容器时。


a=b=c=[1,2,3]

此时,变量a、b、c均指向同一个列表对象的内存地址,而非各自拥有独立的副本。因此,修改其中任意一个变量所指向的内容,其他变量也会随之改变。

例如,若执行 a[1] = 4,则变量b的值也会变为[1, 4, 3]。

你是否真正理解Python中的赋值与拷贝机制?

为了直观展示,我们先看一段示例代码。


>>> import copy
>>> a = [1,2,3,4,['a','b']]
>>> b = a
>>> c = copy.copy(a)
>>> d = copy.deepcopy(a)
>>> a.append(5)
>>> print(a)
[1, 2, 3, 4, ['a', 'b'], 5]
>>> print(b)
[1, 2, 3, 4, ['a', 'b'], 5]
>>> print(c)
[1, 2, 3, 4, ['a', 'b']]
>>> print(d)
[1, 2, 3, 4, ['a', 'b']]
>>> a[4].append('c')
>>> print(a)
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> print(b)
[1, 2, 3, 4, ['a', 'b', 'c'], 5]
>>> print(c)
[1, 2, 3, 4, ['a', 'b', 'c']]
>>> print(d)
[1, 2, 3, 4, ['a', 'b']]######内存地址########
>>> id(a)44350024>>> id(b)44350024>>> id(c)44410440>>> id(d)44410760

一、核心概念与原理

在深入探讨赋值、copy和deepcopy之前。

有必要先了解Python内存中变量的存储机制。

在高级编程语言中,变量本质上是对内存地址的抽象。对于Python而言,所有变量都是对象,其存储采用引用语义:变量仅保存其所指对象在内存中的地址,而非对象本身。

2、赋值操作

在Python中,对象赋值即简单的引用复制,这与C++的行为不同。示例如下。


list_a = [1,2,3,"hello",["python","C++"]]
list_b = list_a

在此情况下,list_b与list_a指向同一块内存区域,list_b仅是list_a的别名,二者共享引用。

可通过 list_b is list_a 进行判断,若返回true,则表明二者地址相同且内容一致。也可使用 id(x) for x in list_a, list_b 来查看两个列表的具体地址。

赋值操作(包括作为参数传递或返回值)不会开辟新的内存空间,仅复制了新对象的引用。除list_b这一名称外,无其他内存开销。

若修改list_a,list_b的内容也会受影响;反之,修改list_b同样会影响list_a。

3、浅拷贝

浅拷贝会创建一个新的对象,但其内容包含的是原对象中元素的引用。

浅拷贝主要有三种实现方式:切片操作、工厂函数以及copy模块中的copy函数。

例如,针对上述list_a进行浅拷贝操作。

切片操作:list_b = list_a[:] 或 list_b = [each for each in list_a]。

工厂函数:list_b = list(list_a)。

copy函数:list_b = copy.copy(list_a)。

经浅拷贝生成的list_b不再是list_a本身,使用is判断可知二者不是同一对象,id查看结果显示它们不指向同一内存块。但通过 id(x) for x in list_a 和 id(x) for x in list_b 对比可见,二者包含的元素地址是相同的。

在此场景下,list_a和list_b被视为不同的对象,理论上修改list_b不应影响list_a。例如执行 list_b.append([4,5])。

但需注意,浅拷贝之所以称为“浅”,是因为它仅拷贝了一层。若list_a中包含嵌套列表,修改情况将发生变化。

执行 list_a[4].append("C") 后,查看list_b会发现其内容也发生了变化。原因在于修改了嵌套列表:修改外层元素会改变引用指向,而修改嵌套列表中的元素时,列表本身的地址未变,二者仍指向同一位置。

4、深拷贝

深拷贝仅有一种形式,即copy模块中的deepcopy函数。

与浅拷贝相对,深拷贝会复制对象的所有元素,包括多层嵌套的元素。因此,其时间和空间开销相对较高。

同样针对list_a,若使用 list_b = copy.deepcopy(list_a),后续修改list_b将不会影响list_a。即使嵌套列表层次更深,也不会产生任何影响,因为深拷贝生成的对象是一个全新的独立对象,与原对象再无关联。

二、关于拷贝的注意事项

1、对于非容器类型,如数字、字符及其他“原子”类型,不存在拷贝概念,生成的均为原对象的引用。

2、若元组变量值中包含原子类型对象,即使采用深拷贝,最终得到的仍是浅拷贝效果。

以上为个人经验总结,希望能为大家提供参考,也希望大家多多支持本站。

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。