问题描述:
def func(x=[], y=[6, 7]):
x.append(8)
y.append(8)
return x + y
a, b = [1, 2], [3, 4]
t = func(x=a)
t = func(y=b)
print(func(), end=";")
上述程序输出结果是什么,为什么?
问题解答:
关键点,地址的理解。
第一次调用x=a,改变的是a的值,并不是默认参数x的值,但是确确实实改变了y的值。第二次调用y=b,改变的是b的值,并不是改变的默认参数y的值,但是确确实实改变了x的值。最后使用的默认参数是改变后的x和y的值。用地址理解比较容易,涉及四个地址,分别是默认参数(x,y),传入参数(a,b)四个地址。地址里面的内容在不断变化。
————————————————————————————————————
第一次调用 func(x=a)
t = func(x=a)
x
被赋值为a
的地址,即x
和a
指向同一个列表[1, 2]
。y
使用默认参数的地址,即[6, 7]
。x.append(8)
改变了a
的内容,a
变为[1, 2, 8]
。y.append(8)
改变了默认参数y
的内容,默认参数y
变为[6, 7, 8]
。- 返回
[1, 2, 8] + [6, 7, 8]
,即[1, 2, 8, 6, 7, 8]
。
第二次调用 func(y=b)
t = func(y=b)
x
使用默认参数的地址,即已经被修改过的[8]
。y
被赋值为b
的地址,即y
和b
指向同一个列表[3, 4]
。x.append(8)
改变了默认参数x
的内容,默认参数x
变为[8, 8]
。y.append(8)
改变了b
的内容,b
变为[3, 4, 8]
。- 返回
[8, 8] + [3, 4, 8]
,即[8, 3, 4, 8]
。
第三次调用 func()
print(func(), end=";")
x
使用已经被修改过的默认参数的地址,即[8, 8]
。y
使用已经被修改过的默认参数的地址,即[6, 7, 8]
。x.append(8)
改变了默认参数x
的内容,默认参数x
变为[8, 8, 8]
。y.append(8)
改变了默认参数y
的内容,默认参数y
变为[6, 7, 8, 8]
。- 返回
[8, 8, 8] + [6, 7, 8, 8]
,即[8, 8, 8, 6, 7, 8, 8]
。
总结
- 默认参数
x
和y
是在函数定义时初始化的,并且在不同的函数调用之间共享。 - 第一次调用
func(x=a)
改变了a
和默认参数y
的内容。 - 第二次调用
func(y=b)
改变了b
和默认参数x
的内容。 - 第三次调用
func()
使用已经被修改过的默认参数x
和y
的内容。
最终输出结果是:
[8, 8, 8, 6, 7, 8, 8];
通过这种理解,我们能更清晰地看到参数的变化过程和共享机制。