python对象与变量的赋值和拷贝

python对象与变量的三种操作:
引用赋值、浅拷贝、深拷贝

引用赋值:
变量【各个引用】指向同一对象的内存地址【值相等、地址相同】
针对不可变对象,改变其中某个引用的值,这个引用指向的对象地址和值会改变,其它引用的值与地址都不变。
针对可变变量,改变其中某个引用的值,各个引用指向的内存地址不变,值都变为修改后的。
因为不可改变对象不可在原处改变,所以修改值相当于创建了新对象,指向的地址也就改变了。
可改变对象可以在原处改变值,并没有创建新对象,所以各个变量指向的内存地址不会改变。

# 引用赋值:可改变对象
a = ["人生苦短", "学python"]
b = a
print(id(a), id(b))
if a is b:
    print("a is b")
if a == b:
    print("a == b")
b.append("!")
print("修改可改变对象某个引用的值")
print(id(a), id(b))
if a is b:
    print("a is b")
if a == b:
    print("a == b")
52224408 52224408
a is b
a == b
修改可改变对象某个引用的值
52224408 52224408
a is b
a == b
# 引用赋值:不可改变对象
a = "人生苦短, 学python"
b = a
print(id(a), id(b))
if a is b:
    print("a is b")
if a == b:
    print("a == b")
b = "python在路上"  # 创建了新对象
print("修改不可改变对象某个引用的值")
print(id(a), id(b))  # 内存地址改变
if a is not b:
    print("a is not b")
if a != b:
    print("a != b")
11743008 11743008
a is b
a == b
修改不可改变对象某个引用的值
11743008 11703816
a is not b
a != b

浅拷贝:
切片操作[:]、工厂函数list、copy函数copy.copy()
1.浅拷贝会产生新的对象,即有新的内存地址,但里边的元素是引用原对象的元素,所以成员地址不会改变
2.修改成员的值相当于创建了新对象,成员的地址会改变,但整体地址不会改变--b不影响a
3.浅拷贝只拷贝单层,不会拷贝嵌套【列表成员包含列表,修改内层列表的值,都会改变】--即b影响a

a = ["人生苦短", "学python"]
b = a[:]  # 创建新对象 a,b指向不同的内存地址
print(id(a), id(b))
if a is b:
    print("a is b")
if a == b:
    print("a == b")
for x in range(len(a)):  # 元素的内存地址是一致的
    print(id(a[x]), id(b[x]))
b[1] = "."  # b[1]成员指向新对象
print("---浅拷贝修改成员的值---")
for x in range(len(a)):  # 元素的内存地址是一致的
    print(id(a[x]), id(b[x]))  # b[1]地址改变
print(a, b)  # a的值不会改变,b的值改变
print(id(a), id(b))  # 内存地址不变
11723160 11032296
a == b
11728320 11728320
11751736 11751736
---浅拷贝修改成员的值---
11728320 11728320
11751736 10137856
['人生苦短', '学python'] ['人生苦短', '.']
11723160 11032296
import copy
a = ["人生苦短",  "学python", [1, 2, 3]]
b = copy.copy(a)
print(id(a), id(b))
if a is b:
    print("a is b")
if a == b:
    print("a == b")
for x in range(len(a)):
    print(id(a[x]), id(b[x]))
a[2].append(4)   # 操作列表成员 a,b值都会改变但是地址不会变操作的是同一个对象
print(id(a[2]), id(b[2]))
print(a, b)
61074128 61074888
a == b
60749248 60749248
60772664 60772664
61073888 61073888
---浅拷贝修改成员列表中成员的值---
61073888 61073888
['人生苦短', '学python', [1, 2, 3, 4]] ['人生苦短', '学python', [1, 2, 3, 4]]

深拷贝:
copy函数copy.deepcopy()
1.深拷贝会产生新的对象,即有新的内存地址,但里边的元素是引用原对象的元素,所以成员地址不会改变【除去嵌套的复杂结构会发生改变】
2.操作拷贝来的对象不会影响原始数据

import copy
a = ["人生苦短",  "学python", [1, 2, 3]]
b = copy.deepcopy(a)
print(id(a), id(b))  # 不是同一个对象
if a is b:
    print("a is b")
if a == b:
    print("a == b")
for x in range(len(a)):
    print(id(a[x]), id(b[x]))
b.append(4)
b[2].append(4)
print(a, b)  # 深拷贝b的值不再影响a
44755664 44756424
a == b
44430784 44430784
44454144 44454144
44755424 44756384
['人生苦短', '学python', [1, 2, 3]] ['人生苦短', '学python', [1, 2, 3, 4], 4]

 

你可能感兴趣的:(Python)