深入剖析Python 数据类型与内存原理(最新推荐)
作者:小呀小叮当~
Python 中的一切皆对象,但变量真的“存储”数据吗?为什么
a = 10改成a = 20后,内存地址会变?本文将带你从基础到底层,彻底搞懂 Python 变量、数据类型与内存管理的秘密!
前言
Python 虽然是高级语言,但理解它的变量与内存模型是写出高效、可控代码的基础。很多初学者会被以下问题困扰:
- 为什么
a = 10和b = 10的id相同? - 为什么列表可以被原地修改,而整数不行?
- Python 的垃圾回收机制到底怎么工作?
- 为什么
is和==有时候表现不同?
本文将一一解答这些问题,并通过实战代码加深理解。
变量是什么?
在 Python 中,变量不是存储数据的容器,而是对象的引用。可以把变量理解为“指向对象的标签”。
a = 10 b = a print(id(a), id(b)) # 两者的内存地址相同
a和b都指向整数对象10,当执行a = 20时,a并不会修改原对象,而是重新指向了一个新的对象。
Python 的数据类型
Python 内置了丰富的数据类型,主要分为两大类:不可变类型 和 可变类型。
数字类型
x = 10 # int y = 3.14 # float z = 3 + 4j # complex
特点:
- 数字类型为不可变对象。
- 对数字重新赋值会创建新对象。
字符串类型
s = "Hello" print(s.upper()) # "HELLO" print(s) # 原字符串未被修改
字符串是不可变对象,每次操作都会生成新对象。
布尔类型
is_ready = True print(isinstance(is_ready, bool)) # True
布尔值是特殊的整数类型,True 等价于 1,False 等价于 0。
列表、元组、字典、集合
lst = [1, 2, 3] # 可变
tpl = (1, 2, 3) # 不可变
dct = {"a": 1} # 可变
st = {1, 2, 3} # 可变
可变对象可以被原地修改,而不可变对象修改后会返回新的对象。
变量与内存
id() 函数与内存地址
id() 用于返回对象的“内存标识”,通常是对象的内存地址。
a = 10 b = 10 print(id(a), id(b)) # 相同(小整数缓存)
当 a = 20 时,a 指向了一个新的内存地址。
可变对象与不可变对象
- 可变对象(列表、字典、集合):原地修改不会更换内存地址。
- 不可变对象(整数、字符串、元组):每次修改会生成新对象。
lst = [1, 2, 3] print(id(lst)) lst.append(4) print(id(lst)) # 地址不变 s = "abc" print(id(s)) s += "d" print(id(s)) # 地址发生变化
引用计数与垃圾回收
Python 使用 引用计数 + 垃圾回收机制 管理内存。
import sys a = [1, 2, 3] print(sys.getrefcount(a)) # 查看引用计数
当对象的引用计数为 0 时,Python 的垃圾回收器会自动释放该对象。
小整数缓存与字符串驻留
Python 会对一些对象进行缓存,以提升性能:
- 小整数缓存:
-5 ~ 256的整数对象会被缓存。 - 字符串驻留:常见短字符串会被重用。
a = 256 b = 256 print(a is b) # True x = "hello" y = "hello" print(x is y) # True
is 与 == 的区别
is:判断两个变量是否指向同一个对象(比较内存地址)。==:判断两个对象的值是否相等。
a = [1, 2, 3] b = [1, 2, 3] print(a == b) # True(值相等) print(a is b) # False(内存地址不同)
深拷贝与浅拷贝
当我们复制对象时,要注意 Python 的拷贝机制:
import copy lst1 = [[1, 2], [3, 4]] lst2 = lst1.copy() # 浅拷贝 lst3 = copy.deepcopy(lst1) # 深拷贝 lst1[0][0] = 99 print(lst2) # [[99, 2], [3, 4]] 受影响 print(lst3) # [[1, 2], [3, 4]] 不受影响
- 浅拷贝:只复制最外层引用,内部对象共享。
- 深拷贝:递归复制所有对象。
内存优化技巧
避免不必要的对象拷贝
# 不要频繁用 + 拼接字符串
result = []
for i in range(1000):
result.append(str(i))
print("".join(result))
使用生成器减少内存占用
def gen():
for i in range(1000):
yield i
for x in gen():
print(x)
利用 __slots__ 限制对象属性
class Person:
__slots__ = ('name', 'age')
及时清理无用引用
del obj
实战示例
# 变量与内存地址示例 x = [1, 2, 3] y = x print(id(x), id(y)) # 两者相同 y.append(4) print(x) # [1, 2, 3, 4],因为是同一个列表引用 # 不可变对象示例 a = 10 b = a print(id(a), id(b)) # 相同 a += 1 print(id(a), id(b)) # a 变了,b 不变
总结
- Python 变量是“标签”,指向内存中的对象。
- 不可变对象(数字、字符串、元组)每次修改会生成新对象。
- 可变对象(列表、字典、集合)原地修改内存地址不变。
- Python 使用引用计数和垃圾回收机制管理内存。
- 小整数缓存、字符串驻留是性能优化手段,但不要依赖内部实现。
- 理解
is与==、浅拷贝与深拷贝是写好 Python 的关键。
到此这篇关于深入剖析Python 数据类型与内存原理(最新推荐)的文章就介绍到这了,更多相关Python 数据类型与内存原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
