先上代码:
a = [[1],[2],[3]]
b = [[4,5],[6,7],[7,8]]
for i,j in zip(a,b):print(i,j)i = [9]#i[0] = 8j[:2]=[1,2]print(i, j)
print(a)
print(b)
运行的结果:
[1] [4, 5]
[9] [1, 2]
[2] [6, 7]
[9] [1, 2]
[3] [7, 8]
[9] [1, 2]
[[1], [2], [3]]
[[1, 2], [1, 2], [1, 2]]
可以看到修改i的值不会造成数组a的值的修改,而修改j的值会造成数组b的值的修改,这是为什么呢?
引用传递和值传递
引用传递(Pass by Reference)
在引用传递中,函数接收的是变量的地址,也就是对象的引用。
当你把一个可变对象(如列表、字典等)传递给函数时,函数内部对该对象的修改会影响到原始的对象。
这是因为函数接收的是对象的引用,而不是对象的副本。
示例:
def modify_list(lst):lst[0] = 'changed'my_list = [1, 2, 3]modify_list(my_list)print(my_list) # 输出 ['changed', 2, 3]
值传递(Pass by Value)
在值传递中,函数接收的是变量的值的副本。
当你把一个不可变对象(如整数、字符串等)传递给函数时,函数内部对该变量的修改不会影响到原始的变量。
这是因为函数接收的是变量的值的副本,而不是变量本身。
示例:
def modify_int(x):x = 'changed'my_int = 10modify_int(my_int)print(my_int) # 输出 10
总的来说,在 Python 中,变量的赋值行为遵循以下规则:
对于可变对象,变量存储的是对象的引用,即引用传递。
对于不可变对象,变量存储的是对象的值,即值传递。
对一开始的问题做出简化
a = [[1],[2],[3]]
b = [[4,5],[6,7],[7,8]]
c = a
c[0]=[8]
print(a)
这个c按理说是a的一个副本,但是为什么对c修改会对a造成影响呢?
当我们执行 c = a时,c 并不是 a 的副本,而是指向了 a 中同样的列表对象。也就是说,a 和 c 指向的是同一块内存地址。
然后当我们执行 c[0] = [8] 时,我们是在修改 c 指向的那个列表的第一个元素。但是由于 a 和 c 指向的是同一个列表对象,所以这个修改同时也影响到了 a。
这就是为什么打印 a 的结果会变成 [[8], [2], [3]]。
如果你想创建 a的副本,而不是让 c 指向同一个列表对象,可以使用以下方式:
a = [[1], [2], [3]]
b = [[4, 5], [6, 7], [7, 8]]
c = a[:] # 或者 c=copy.copy(a) 或 c = copy.deepcopy(a)
c[0] = [8]
print(a) # 输出 [[1], [2], [3]]
print(c) # 输出 [[8], [2], [3]]
在最开始的问题中
a = [[1],[2],[3]]
b = [[4,5],[6,7],[7,8]]
for i,j in zip(a,b):print(i,j)i = [9] #这个是值传递#i[0] = 8 #这个是引用传递 j[:2]=[1,2] #这个是引用传递print(i, j)
print(a)
print(b)