这一部分看似很容易让人糊涂,实际上只需要记住四点,其他一切现象都可以推导而出。
- Python的变量(不管存储的是可变对象还是不可变对象)本质类似于指针,存储的是引用
- Python的不可变对象(只有turple, int, float, bool, string)不可以在原处被修改,想修改必须创建一个新的对象; 可变对象可以在原处被修改。
- Python中,不可变对象有缓存机制,相同的不可变对象在一定范围内只有一个; 相同的可变对象可以有多个。
- python的list, set, dict本质都是引用的集合; 切片操作会创建一个新的引用集合, 但是新引用集合里的引用是直接复制原来的引用。
补充:
- Python的 == 只检查两边的值是否相等, 而用is检查两边是否指向同一对象。
- 整型数字的缓存范围为[-5, 256],即变量值相等且在[-5, 20]范围内的所有变量都是同一个对象; 字符串默认缓存长度4096,即变量值相等且长度在4096以内的所有字符串变量是同一个对象。
我们通过以上的四点可以得出以下推论:
- python的赋值全部都是传递引用,所以a = b之后, a is b一定是True。
-
# 字符串是不可变对象,heap中只有一个'123' a = '123' b = '123' a is b # True # list是可变对象,heap中可以创建多个[1,2,3] a = [1,2,3] b = [1,2,3] a is b # False
-
a = [1,2,3] b = a a[0] = 4 print(b) # [4,2,3] a is b # True a = (1,2,3) b = a a is b # True, 因为Python中所有的赋值都是传递引用 a[0] = 4 # TypeError: 'tuple' object does not support item assignment b = (4,5,6) print(a) # (1,2,3) a is b # False, 创建元组(4,5,6)后将b指向这个元组,但是a的指向没变
- 切片操作本质是浅拷贝,虽然a is b是False,但是它们中的元素(引用)指向同一对象,所以修改a的可变元素,b的元素也会改变。
a = [1,[2]] b = a[:] a is b # False a[0] is b[0] # True a[1] is b[1] # True a[1].append(3) print(a) # [1, [2, 3]] print(b) # [1, [2, 3]]
要进行deeocopy, 先import copy, 再使用copy.deepcopy()函数。