Python中的引用与拷贝
前言
最近在整理 Python 的笔记,整理到字典的复制的时候,重新学习了下其中的赋值与复制差别
其中容易弄混的地方清晰许多,进行输出下,上篇干货
先上个赋值的示例
a = 1
b = a
print(f'a的值为{a}') # a的值为1
print(f'b的值为{b}') # b的值为1
a = 5
print(f'a的值为{a}') # a的值为5
print(f'b的值为{b}') # b的值为1
可以发现就是一个简单的赋值,清晰明了,不会有任何疑惑是吧
我们尝试换下值的数据类型
a = [0, 1, 2, 3, 4, 5]
b = a
a[1] = 'Hello!'
print(f'a的值为{a}') # a的值为[0, 'Hello!', 2, 3, 4, 5]
print(f'b的值为{b}') # b的值为[0, 'Hello!', 2, 3, 4, 5]
同第一个代码示例的写法,但是为什么其中的 b
竟然随着 a
进行改变了
这就是今天要讲的点,Python 的引用与复制
这个知识点不仅在变量传递的时候使用到,在进行字典操作的时候也很常见,不了解清楚很容易搞混
核心知识点
不讲废话,直入主题,为什么会造成这种差异?
这是因为数值的数据类型特性(是否可变)所导致的
我们知道 Python 有 7 种标准的数据类型
- 字符串
- 字典
- 元组
- 数字
- 列表
- 集合
- 布尔
而如果根据是否可变的角度进行分类,可以分为 2 类
- 可变数据类型:
- 列表类型(list)
- 字典类型(dict)
- 集合类型(set)
- 不可变数据类型:
- 数字类型(int, float, complex)
- 字符串类型(str)
- 元组类型(tuple)
可变与不可变数据是对于引用地址来说
不可变数据类型不允许变量的值发生变化,如果改变,相当于新建一个对象
记住了以上这句话,其实就掌握了全篇核心的知识点🙃
例如你尝试对字符串进行修改,会抛出异常
# 创建一个字符串
my_string = "Hello"
# 尝试修改字符串的第一个字符
my_string[0] = "h"
"""
发生异常: TypeError
'str' object does not support item assignment
"""
引用
字符串
字符串类型属于不可变数据类型
a = "1"
b = a
print(f"a的值是:{a},id是:{id(a)}") # a的值是:1,id是:1412627914544
print(f"b的值是:{b},id是:{id(b)}") # b的值是:1,id是:1412627914544
a = "5"
print(f"a的值是:{a},id是:{id(a)}") # a的值是:5,id是:1412630962672
print(f"b的值是:{b},id是:{id(b)}") # b的值是:1,id是:1412627914544
可以发现在第一次 a
赋予 1 的时候,两者的内存地址是相同的
也就是引用的是一个内存空间(使用 id 检测数值一样)
而在第二次对 a
进行赋值的时候
由于字符串属于不可变,不能改变 "1"
这个对象,所以只能新建一个对象 "5"
然后赋值操作,a
的引用对象发生改变,变成了使用对象 "5"
而 b
的值是在第一次赋值时被复制的,使用的是对象 "1"
由于 "1"
这个对象没有发生改变,所以 b
的值 "1"
。
也就是说为 a
第二次赋值的时候,相当于重新开辟了个内存空间
可以发现示例中,使用 id 检测数值不一样了
其他数据类型也是类同,下面处字典类型以外仅写示例,就不进行讲解了
只要记住赋予变量的数据类型是否可变即可
数字
数字类型属于不可变数据类型
a = 1
b = a
print(f"a的值是:{a}") # a的值是:1
print(f"b的值是:{b}") # b的值是:1
a = 5
print(f"a的值是:{a}") # a的值是:5
print(f"b的值是:{b}") # b的值是:1
元组
元组类型属于不可变数据类型
a = (1, 1)
b = a
print(f"a的值是:{a}") # a的值是:(1, 1)
print(f"b的值是:{b}") # b的值是:(1, 1)
a = (1, 2)
print(f"a的值是:{a}") # a的值是:(1, 2)
print(f"b的值是:{b}") # b的值是:(1, 1)
列表
列表类型属于可变数据类型
a = [1, 2, 3]
b = a
print(f"a的值是:{a}") # a的值是:[1, 2, 3]
print(f"b的值是:{b}") # b的值是:[1, 2, 3]
a.append(4)
print(f"a的值是:{a}") # a的值是:[1, 2, 3, 4]
print(f"b的值是:{b}") # b的值是:[1, 2, 3, 4]
字典
字典类型属于可变数据类型
a = {"key1": "a", "key2": "b", "key3": "c"}
b = a
print(f"a的值是:{a}") # a的值是:{'key1': 'a', 'key2': 'b', 'key3': 'c'}
print(f"b的值是:{b}") # a的值是:{'key1': 'a', 'key2': 'b', 'key3': 'c'}
a["key4"] = "d"
print(f"a的值是:{a}") # a的值是:{'key1': 'a', 'key2': 'b', 'key3': 'c', 'key4': 'd'}
print(f"b的值是:{b}") # a的值是:{'key1': 'a', 'key2': 'b', 'key3': 'c', 'key4': 'd'}
偷懒
码累了….,,偷会懒😅
其他类似就不写了
总结
- 不可变数据类型的数据进行多次赋值,是采用新建立对象
- 可变数据类型的数据进行多次赋值,是采用引用相同内存空间,而非建立新对象