为什么 Python 默认参数必须用不可变对象?
话不多说,上代码:
|
|
我们在这段代码中:
定义了一个位置参数 x,一个一个默认参数 A,A 的默认值为空列表,另一个默认参数 B,B 的默认值为一个空字符串,在函数体中定义了一个变量 C,并也给 C 传递了一个空列表。
大家猜猜函数执行会输出怎样一个结果?
|
|
大家猜到了这个结果了吗?猜到的朋友都是大佬,下面的内容就可以略过了。没有猜到的朋友也不要慌,毕竟这玩意儿有点坑。。。
在解释这个结果之前,大家需要复习一下 Python 中可变对象和不可变对象这两个概念:
- 可变对象:对象指向的内存中的值会改变,当更改这个变量的时候,还是指向原来内存中的值,并且在原来的内存值进行原地修改,并没有开辟新的内存(list、dict、set);
- 不可变对象:对象所指向的内存中的值不能被改变,当改变这个变量的时候,原来指向的内存中的值不变,变量不再指向原来的值,而是开辟一块新的内存,变量指向新的内存(int、float、str、tuple、bool、None)。
概念复习完了就开始进入正题了:
在Python程序中,函数在被定义创建时,Python就会为默认参数分配一块儿空间。在这个程序中,为默认变量 A 分配了一个内存地址,其中的值为一个空列表,为 B 也分配了一块儿空间,值为空字符串:
地址:0x0001 值:[] ==> A
地址:0x0002 值:'' ==> B
Python 在调用函数时,会直接将在函数定义时得到的内存地址复制给默认参数!
因此会在调用函数时出现下面的内存变化(内存地址为了方便看才排列这样有序的,实际程序里不可能这样):
当第一次调用函数时:
|
|
函数执行完后内存指向:
地址:0x0001 值:['1'] ==> A
地址:0x0002 值:''
地址:0x0003 值:['1'] ==> C
地址:0x0004 值:'1' ==> B
当第二次调用函数时:
|
|
函数执行完后内存指向:
地址:0x0001 值:['1', '2'] ==> A
地址:0x0002 值:''
地址:0x0003 值:['2'] ==> C
地址:0x0004 值:'2' ==> B
当第三次调用函数时:
|
|
函数执行完后内存指向:
地址:0x0001 值:['1', '2', '3'] ==> A
地址:0x0002 值:''
地址:0x0003 值:['3'] ==> C
地址:0x0004 值:'3' ==> B
经过俺的这番讲解,朋友们你们学废了吗?
为了避免以后在程序中出现莫名其妙的 Bug,大家要记住在 Python 程序中
默认参数的值应该为不可变对象!!!
默认参数的值应该为不可变对象!!!
默认参数的值应该为不可变对象!!!