python函数默认参数的一个坑

示例1

def func(a,b=[]):
    b.append(a)
    print(b)

func(1)
func(2)
func(3)

有个考python特性的面试题,func(3)的时候,b 这个list是啥。

输出结果:

[1]
[1, 2]
[1, 2, 3]

示例2

def func(a,b=1):
    b += a
    print(b)

func(1)
func(2)
func(3)

输出结果:

2
3
4

分析

这里引用一段的概率

  • 栈(操作系统):
    由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆(操作系统):
    一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。

根据上面的概率但是正常输出应该是[3]呀,很多其他语言都是这样。这里很明显‘b’没有被回收,‘a’是正常的回收了。根据第二个例子,发现不是一般情况,“数组”和普通数值型不一样的效果。据此分析:

引用传递

def func(a b=[])   --->  代码进行到这里定义一个函数(1)

b = []   ---> 设置默认参数,在堆中创建一个b = [] (2)
              创建一个"栈",在栈中创建 a, b = (2)的地址指针位置, (3)
func(1)   --->  执行函数func(1),修改栈中a = 1
b.append(a)---> 调用栈中的b 指针(引用传递),将a到列表-->b
print(b)
                函数func(1)执行完,栈系统自动回收,b指针消失。但是b的值已经修改。

值传递

def func(a b=1)   --->  代码进行到这里定义一个函数(1)
                         创建一个"栈",在栈中创建 a, b = 1, (2)
func(1)   --->  执行函数func(1),修改栈中a = 1,
b += a      --->   修改过栈中 b = 1 + a
print(b)                       
                函数func(1)执行完,栈系统自动回收,a,b消失。

Python的数组类型是用的引用传递,普通数字是值传递,这就是python和其他语言处理默认参数方式不一样吧,其他语言再执行函数之前,初始化一个栈,所有的参数都重新初始化到新的栈中。

如上就是我的分析,但是本人技术有限怕理解不对,希望大神不吝赐教!记下来只是提醒自己python有这样一个特性在这,需要注意。

文章目录
  1. 1. 示例1
  2. 2. 示例2
  3. 3. 分析
    1. 3.1. 引用传递
    2. 3.2. 值传递
|