Python中没有给需要传入参数的函数传参会发生什么

Python中没有给需要传入参数的函数传参会发生什么?这个问题可能很多人都没有想过,因为我们在设计和使用程序的时候通常不会这么做,而我思考这个问题也是来源于一个师兄给我发的Festo开发者网站的登陆问题,代码很简答。

def func(par=[]):
    par.append("a")
    return par

print(len(func()+func()+func()))

第一直觉输出是3,但是当我写代码验证的时候发现事情没有那么简单,代码结果是7!!!

想不通,输出三个返回的列表相加后的结果看看:

>>print(func()+func()+func())
['a', 'a', 'a', 'a', 'a', 'a', 'a']

果然没错,列表里面包含7个元素,但是func()函数的确只被调用了三次。

想不到什么原因,查一波资料没有找到解释,自己用最笨的方法找原因吧。

首先单步调试看看发生了什么:

第一次调用func()的时候par的初始值为:[],返回值为:['a'],没错;第二次的时候par的初始值为:['a'],返回值为:['a','a'];第三次的时候par的初始值为:['a','a'],返回值为:['a','a','a']。

看起来是后一次的函数把前一次的返回值作为参数传入了,为什么会这么做呢,调用的时候分明没有传入任何参数。

开始从内存的角度分析问题,怀疑三次调用读写的是同一块内存,在函数中打印一下变量的地址看看:

def func(par=[]):
    print(id(par))
    par.append("a")
    return par

print(func()+func()+func())

运行结果为:

2676459528776
2676459528776
2676459528776
['a', 'a', 'a', 'a', 'a', 'a', 'a']

三次调用中传入局部变量par的地址都是一样的,说明每次调用都会操作同一块内存,没调用一次func()函数,都会往这块内存中写入一个'a'。刚刚说到第一次调用返回['a'],第二次返回['a','a'],第三次返回值['a','a','a']。按理说三次的和应该是6个a,但是程序输出确是7个a,这里又该如何解释。

 

回到最初的问题:

func()+func()+func()

我们知道“+”是一个双目运算符,两边必须有左值和右值,上式中的func()返回的是par可以看做是一个“指针A”(Python中可变对象是通过“指针”进行传递的),这个“指针A”指向的内存中保存的内容是['a'],这个“指针A”所指向的内容就作为第一个“+”号的左值。前面说到三次调用func()操作的都是同一块内存,所以第二次调用func()的时候往这块内存中又写入了一个'a',内容变为['a','a'],这个时候“指针A”所指向的内容也是['a','a'](因为指向的是同一块内存)。因此前面两个func()+func()运行时的结果是['a','a']+['a','a']==['a','a','a','a'],“+”号返回的是一个新的临时变量,会开辟一个新的内存空间来进行保存。第三次调用func()的时候内存中的值变为['a','a','a'],再加上前面两个的和['a','a','a','a'],结果就是7个‘a’啦。

如果我们事先给一个左值,再加上后面三个func(),结果肯定是6个'a',程序验证一下:

def func(par=[]):
    print(id(par))
    par.append("a")
    return par

print([]+func()+func()+func())

说明以上分析正确。

总结一下:

在Python中如果一个函数设置有可变参数,而我们在调用时没有传入参数,那么Python就会自动分配一个变量作为该函数的参数。

 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值