做视频链接网站网页搜索引擎
脚本中含有默认参数,多次调用该方法,发现该默认值会沿用之前的结果
代码如下:
def func(a, tes=[]):tes.append(a)print(tes)if __name__ == '__main__':for i in range(5):func(i)func(10, [10])for x in "test":func(x)func(110, [101])for x in "@@@":func(x)
输出结果为:
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
[10, 10]
[0, 1, 2, 3, 4, 't']
[0, 1, 2, 3, 4, 't', 'e']
[0, 1, 2, 3, 4, 't', 'e', 's']
[0, 1, 2, 3, 4, 't', 'e', 's', 't']
[101, 110]
[0, 1, 2, 3, 4, 't', 'e', 's', 't', '@']
[0, 1, 2, 3, 4, 't', 'e', 's', 't', '@', '@']
[0, 1, 2, 3, 4, 't', 'e', 's', 't', '@', '@', '@']
执行func(10, [10])和func(110, [101])的时候结果是正常的,但是遍历的时候就出错
这是因为:
函数的参数默认值只会被初始化一次,并且被重复利用。 当参数默认值为可变对象时,若函数调用时不传入参数值,则对该参数的默认值进行的任何操作实际上操作的是同一个对象。
将默认值修改为不可变参数:
def func(a, tes=None):tes = []tes.append(a)print(tes)if __name__ == '__main__':for i in range(5):func(i)func(10, [10])for x in "test":func(x)func(110, [101])for x in "@@@":func(x)
输出就正常了:
[0]
[1]
[2]
[3]
[4]
[10]
['t']
['e']
['s']
['t']
[110]
['@']
['@']
['@']
可变数据类型:list dict set
不可变数据类型:tuple string int float bool
a = [1, 2, 3]
a[1] = 112
print(a)
# [1, 112, 3]
b = (1, 2, 3)
b[1] = 12
# TypeError: 'tuple' object does not support item assignment
a = [1, 2, 3]
b = a
print(id(a))
print(id(b))
a[1] = 112
print(a)
print(b)
print(id(a))
print(id(b))
改变a则b也跟着变,因为他们始终指向同一个地址
1899238159872
1899238159872
[1, 112, 3]
[1, 112, 3]
1899238159872
1899238159872
a = (1, 2, 3)
b = a
print(id(a))
print(id(b))
a = (112, 112)
print(a)
print(b)
print(id(a))
print(id(b))
a改变后,它的地址也发生了变化,而b则维持原来的地址,原来地址中的内容也没有发生变化
2245734362176
2245734362176
(112, 112)
(1, 2, 3)
2245732924608
2245734362176
def func(ls):ls.append("aaa")def func(ls):ls+="aaa"ls = [1, 2, 3]
print(id(ls))
func(ls)
print(ls)
print(id(ls))
可变对象作为参数传入时,在函数中对其本身进行修改,是会影响到全局中的这个变量值的,因为函数直接对该地址的值进行了修改
2397764547648
[1, 2, 3, 'a', 'a', 'a']
2397764547648
def func(ls):ls += "aaa"print(ls, id(ls))ls = "123"
print(id(ls))
func(ls)
print(ls)
print(id(ls))
虽然函数中的a值变了,但是全局中的a值没变,因为函数中的a值已经对应了另外一个地址,而全局中的a值指向的原来地址的值是没有变的
2497344780976
123aaa 2497344781424
123
2497344780976