在 python 中,变量命令,参数传递,都是通过引用来实现。
如果两个变量为同一个引用,那么这两个变量对应的数据一定相同
但是两个对应的数据相同,引用不一定相同。
# 从数据可变与不可变的类型来解析引用
''''
可变数据类型:列表 字典 集合
通过容器的方法来修改其内容,地址不变(引用指向不会发生改变)
通过重新赋值的方式来修改内容,地址改变(引用指向发生改变)
'''
# 列表
my_list = ["a", "b"]
print(f"列表改变前ID:{id(my_list)}") # 2804311679624
my_list.append("c")
print(f"列表方法改变后ID:{id(my_list)}") # 2804311679624
my_list = ["a", "b", "d"]
print(f"列表重新赋值改变后ID:{id(my_list)}") # 2804311679688
# 字典
my_dict = {"name": "小明", "age": 18}
print(f"字典修改之前{id(my_dict)}") # 1876656552768
my_dict["name"] = "小红"
print(f"字典键方式修改之后{id(my_dict)}") # 1876656552768
my_dict = {"name": "小白", "age": 19}
print(f"字典赋值修改之后{id(my_dict)}") # 1876656552840
# 集合
my_set = {"red", "black"}
print(f"集合修改之前{id(my_set)}") # 1683491755400
my_set.update("green")
print(f"集合方法修改之后{id(my_set)}") # 1683491755400
my_set = {"red", "black", "white"}
print(f"集合赋值修改之后{id(my_set)}") # 1683491754504
'''
不可变数据类型
字符串 元组 数字
一旦修改了数据的内容,数据的地址发生改变
'''
# 字符串
my_str = "abc"
print(f"字符串修改之前{id(my_str)}") # 1368298093008
my_str = my_str.replace("c", "d")
print(f"字符串方法修改之后{id(my_str)}") # 1368298120952
my_str = "abe"
print(f"字符串重新赋值之后{id(my_str)}") # 1368299138048
# 元组
my_tup = (1, 2, 3)
print(f"元组修改之前{id(my_tup)}") # 2255037031624
my_tup = (1, 2, 3, 4, [5, 6])
print(f"元组重新赋值修改之后{id(my_tup)}") # 2255035856152
my_tup[4].append(7)
print(f"元组元素为列表修改之后{id(my_tup)}") # 2255035856152
# 数字
my_int = 1
print(id(my_int)) # 140733298270864
my_int1 = my_int
print(id(my_int1)) # 140733298270864
my_int = 2
print(id(my_int)) # 140733298270896
# 对于字符和数字的引用的一些注意点
'''
当python解释器首次启动时,会把小数字(-5~256)和短字符串(长度小于21)缓存到缓冲区中
当在程序中使用这些数字和字符串时 就直接从缓存区中取。
'''
n = 100
m = 100
j = 257
k = 257
print(id(n)) # 140733298274032
print(id(m)) # 140733298274032
print(id(j)) # PyCharm 测试无效 需要在终端测试
print(id(k))
a = "hello"
b = "hello"
print(id(a)) # 2216100228264
print(id(b)) # 2216100228264
由上述测试可以得出:
无论是可变类型还是不可变的数据类型 只要是被重新赋值 它的id就会改变 即引用指向一个新的空间
针对可变数据类型来说:
通过一些方法修改自身的内容,id并没有发生变化
针对不可变类型来说:
只要自身数值发生改变,id就会改变
注意:通过可变类型方法修改不可变类型中的可变元素时,id也不会发生改变