Part 1
偶然看到一道Python面试题(链接):
请写出下面的代码的输出是什么?
实际输出结果为:
很多人会错误地预计list1等于[10],list3等于[‘a’],认为extendList函数的list参数在每一次函数被调用时都会被设置为默认值[]
但是,真实的情况是,默认的list只在函数定义的时候被创建一次。之后不指定list参数地调用extendList函数时,使用的都是同一个list。这是因为带默认参数的表达式是在函数定义的时候被计算的,而不是在函数调用时。
简单的说:一个函数参数的默认值,仅仅在该函数定义的时候,被赋值一次。
Part 2
可是我记得参数是整形的时候不是这样的啊,试一下看看
执行结果:
果然,这一次,每次调用的时候,num的初始值都是5。这又是什么原因呢?
解释:这就牵扯出了Python中的又一对概念———可变对象与不可变对象。列表是可变对象,对于列表的修改,是直接在原值上进行的。而整型是不可变对象,当Python中不可变对象的值发生变化时,只是改变了该对象的引用。譬如这里执行 num += val 时,其实并没有改变num变量原来对一个的那块内存的值,只是又开辟了一块内存,赋值为num+val,然后将num指向了这块地址。
我们可以用id()方法,输出变量的内存地址,就比较直观了。
输出结果:
可以看到,
第一次和第三次调用addNumber()时,num的默认地址是相同的,但赋值操作之后,地址发生了变化。但对于extendList(),是在list的原始地址上直接修改的。