Python变量赋值:深入理解引用与拷贝机制

竹里
竹里
发布时间:2026-10-13| 6人浏览过
原创

本文解析Python中变量赋值的底层逻辑,区分静态与动态对象的传递行为。通过字典与列表的组合示例,演示直接赋值导致的引用共享问题,并对比使用copy()浅拷贝与deepcopy()深拷贝的效果。文章指出,修改可变对象(如列表)会影响原数据,而不可变对象(如字符串、数值)则生成新对象。掌握id()函数检查内存地址,有助于避免意外修改,确保数据独立性。

iamlaosong文

曾遇到一个典型问题:当字典的值包含列表时,若将该列表赋值给一个新变量,随后修改该新变量中的列表元素,会发现原字典中的列表内容也随之改变。

具体案例如下:

dict = {'a':[1,2,3,4,5],'b':2} 
x = dict['a'] 
for i in range(5): 
  x[i] = 0 
print(dict['a']) 

程序执行后的输出结果如下:

[0, 0, 0, 0, 0] 

这一现象揭示了Python赋值操作中“引用”与“拷贝”的核心区别,即赋值过程是传值还是传址。上述问题源于将字典中“a”对应的列表直接赋值给变量x,导致两者指向同一内存地址。若改为将“b”的值(整数)赋值给x,再修改x,则字典dict中的值不会受到影响。

>>> dict = {'a':[1,2,3,4,5],'b':2} 
>>> x = dict['b'] 
>>> x 
2 
>>> x=x+3 
>>> x 
5 
>>> dict 
{'a': [1, 2, 3, 4, 5], 'b': 2} 
>>>  

由此引发思考:在变量赋值传递过程中,究竟何时发生传值(拷贝),何时发生传址(引用)?

1、显式拷贝策略

当不确定赋值行为是引用还是拷贝时,建议显式执行拷贝操作。例如,字典对象自身提供了拷贝方法:

x=dict.copy() 

即使对象本身没有内置拷贝方法,依然可以通过Python标准库中的copy模块进行深拷贝。深拷贝(deepcopy)会递归复制原变量关联的所有数据,在内存中生成一套完全独立的内容。在此过程中,对任一副本的修改均不会影响其他变量。基于前述代码,若改为深拷贝方式,实现如下:

import copy 
dict = {'a':[1,2,3,4,5],'b':2} 
x = copy.deepcopy(dict['a']) 
for i in range(5): 
  x[i] = 0 
print(dict['a']) 

运行结果显示,原字典dict的值未受任何影响。

除了深拷贝,copy模块还提供了浅拷贝(copy)方法。对于简单对象,浅拷贝与深拷贝效果一致;前述字典对象的copy方法即为浅拷贝。

>>> dict
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd=copy.copy(dict)
>>> dd
{'a': [8, 2, 3, 4, 5], 'b': 4}
>>> dd['a'][0]=7
>>> dd
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee=dict.copy()
>>> ee
{'a': [7, 2, 3, 4, 5], 'b': 4}
>>> ee['a'][0]=9
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> ee['b']=5
>>> ee
{'a': [9, 2, 3, 4, 5], 'b': 5}
>>> dict
{'a': [9, 2, 3, 4, 5], 'b': 4}
>>> 

在浅拷贝场景下,修改第一层次(如上文字典b的值)互不影响,但修改第二层次(如上文字典a中的列表值)时,所有关联变量会同步变化。通过检查内存地址(id)可以验证这一点:

>>> id(dict) 
20109472 
>>> id(dd) 
20244496 
>>> id(ee) 
20495072 
>>> id(dd['a']) 
20272112 
>>> id(ee['a']) 
20272112 
>>> id(dict['a']) 
20272112 
>>>  

从输出可见,字典本身及其不同拷贝的id各不相同,但字典a中列表值的id是相同的。若需实现真正意义上的完全独立拷贝,应使用深拷贝。

2、传递规则解析

Python在赋值过程中并不严格区分拷贝与引用,其一般规则为:对静态变量(不可变对象)的传递视为拷贝,对动态变量(可变对象)的传递视为引用。(注:对静态变量首次传递时也是引用,但当尝试修改该静态变量时,由于不可变特性,Python会生成新的内存空间存储新数据)。

字符串、数值、元组均属于静态变量。

列表、字典属于动态变量。

变量结构有时较为复杂,存在嵌套组合现象,例如字典中包含列表,或列表中包含字典。尽管结构复杂,赋值时仍遵循其基础类型的规则。若无法确定具体状况,可通过试验验证,利用id()函数查看变量指向的内存地址是否相同。例如:

>>> a=6 
>>> id(a) 
10413476 
>>> b=a 
>>> id(b) 
10413476 
>>> b=8 
>>> id(b) 
10413452 
>>>  

在修改变量b之前,a和b指向相同的内存地址;修改b后,b指向了新地址,而a保持不变。

以上关于Python变量赋值传递中引用与拷贝方法的解析即为全部内容,希望能为读者提供参考,并欢迎大家继续支持本站。

相关标签:

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

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 算法库。