Skip to main content

Python 基础

Python 值类型和引用类型

Python 中的变量存储机制涉及值类型和引用类型的概念,这对理解内存管理和程序行为至关重要。本章节将简要介绍这两种类型的区别、深拷贝与浅拷贝、特点及注意事项。

1. 值类型

值类型(也称为不可变类型)是指数据在内存中存储为固定值,变量直接持有数据本身。Python中的常见值类型包括:

  • 整型int):如x = 10
  • 浮点型float):如y = 3.14
  • 布尔型bool):如z = True
  • 字符串str):如s = "hello"
  • 元组tuple):如t = (1, 2, 3)

特点:

  • 不可变性:值类型的对象创建后,其内容不可更改。例如,s = "hello"; s += " world"会创建一个新字符串,而不是修改原字符串。
  • 内存分配:当多个变量赋值为相同的值类型对象时,Python可能会重用同一对象(例如小整数或某些字符串),以节省内存。比如值类型的小整数(-5256)和某些字符串可能因 Python 的内存优化而共享引用。
  • 赋值行为:对值类型变量赋值会创建数据的副本,修改新变量不会影响原变量。

示例:

# 在这里,a 和 b 是独立的,修改 b 不会影响 a
a = 10
b = a
b = 20
print(a)  # 输出:10
print(b)  # 输出:20

看下面共享内存的示例:

>>> a=99999
>>> b=99999
>>> a is b
False

# 例如小整数 会共享内存 -5~256
>>> a=256
>>> b=256
>>> a is b
True

>>> a=257
>>> b=257
>>> a is b
False

2. 引用类型

引用类型(也称为可变类型)是指变量存储的是对象的引用(内存地址),而不是数据本身。Python中的常见引用类型包括:

  • 列表list):如lst = [1, 2, 3]
  • 字典dict):如d = {"key": "value"}
  • 集合set):如s = {1, 2, 3}

特点:

  • 可变性:引用类型的对象可以直接修改内容。例如,lst.append(4)会修改原列表。
  • 引用传递:赋值时,变量指向同一内存地址。多个变量可能引用同一对象,修改会影响所有引用该对象的变量。
  • 内存管理:Python通过引用计数管理内存,当引用计数为零时,垃圾回收机制会释放内存。也就是说一个对象被多一个变量引用,计数器就+1,少一个变量引用计数器就 -1 ,当对象的引用计数为0时会是否内存。

示例:

lst1 = [1, 2, 3]
lst2 = lst1
lst2.append(4)
print(lst1)        # 输出:[1, 2, 3, 4]
print(lst2)        # 输出:[1, 2, 3, 4]

lst1 和 lst2 指向同一列表对象,修改 lst2 会同时影响 lst1。

3. 深拷贝与浅拷贝

引用类型的特性可能导致意外的数据修改,因此需要了解拷贝机制:

  • 浅拷贝:只复制对象的引用,嵌套对象仍共享内存。使用copy.copy()实现。
  • 深拷贝:递归复制对象及其所有嵌套对象。使用copy.deepcopy()实现。

示例:

import copy
lst1 = [[1, 2], 3]
lst2 = copy.copy(lst1)      # 浅拷贝
lst3 = copy.deepcopy(lst1)  # 深拷贝

lst2[0][0] = 99  # 由于是浅拷贝,嵌套对象是引用类型,修改后会影响以前的值
lst2[1] = 4      # 对象是值类型,拷贝后是一个新的内存区域,修改后不影响就的值

print(lst1)      # 输出:[[99, 2], 3]
print(lst2)      # 输出:[[99, 2], 4]
print(lst3)      # 输出:[[1, 2], 3]

浅拷贝修改嵌套对象会影响原对象,而深拷贝完全独立。

4. 注意事项

  • 值类型适合存储不可变数据,如配置参数、计数器等,确保数据一致性。
  • 引用类型适合动态数据结构,如列表或字典,用于需要频繁修改的场景。
  • 拷贝选择:在处理复杂数据结构时,使用深拷贝避免意外修改;浅拷贝则更轻量,适合简单场景。
  • 使用 is 检查对象是否相同(引用),使用 == 检查值是否相等。
  • 避免直接修改函数参数中的引用类型对象,建议使用返回值或深拷贝。