鱼C论坛

 找回密码
 立即注册
查看: 902|回复: 3

默认值参数只被初始化一次,使用可变序列为参数带来的困扰!

[复制链接]
发表于 2020-3-27 15:17:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
def demo(newitem,old_list=[]):
    old_list.append(newitem)
    return old_list

print(demo('a')) 
print(demo('b')) 

上面代码因默认值参数默认值被赋成一个空列表,而使调用出现问题,可用下面代码修正。
def demo(newitem,old_list=None):
    if old_list is None:
        old_list=[]
    old_list.append(newitem)
    return old_list

print(demo('a')) 
print(demo('b')) 

为什么给默认参数赋值成None可以解决这个问题了呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-3-27 15:31:59 | 显示全部楼层
因为列表是可变类型,而 None 是不可变类型
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-27 15:44:45 | 显示全部楼层
list 有方法来改变它本身,NoneType 没有
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-3-27 15:56:03 | 显示全部楼层
因为函数只在最开始定义的时候进行一次解析,在这时为默认值参数分配id。因此每次调用的时候都会去扫描此id下的内容
再来说一下可变量类型和不可变类型,这里若默认值参数是不可变类型,在函数中对其进行修改实际上是被认为重新定义了一个同名变量(这一点可以print变量的id看一下就知道了),而若默认值参数是可变类型,在函数中对其进行修改操作就是对其本身进行的操作,不会被认为是重新定义了一个同名变量。
这是为什么呢?
答案如下:
对于不可变类型的变量,若是在函数内部进行修改的话,会有歧义,无法识别到底是修改同名的全局变量,还是定义一个同名的局部变量(因为修改和定义方式是一样的)。因此在函数内若使用不可变类型的全局变量时需要使用global进行明确指出。
对于可变类型,则不存在这种歧义,若是在函数内部修改一个与全局变量同名的变量,不会被认为是要创建一个同名的局部变量(因为修改和定义方式是不一样的),当在函数内没有定义一个与全局变量同名的局部变量,那么修改一个同名的变量时,能够明确就是修改全局变量。

因此,若是打算用一个默认值的可变类型是不行的。
实际上你的第二种写法,完全就是在函数中重新创建了一个同名变量,因为默认值没指定类型,调用参数的时候可以掺进来任何类型的参数,若没有传进来该参数,则会执行if语句,定义一个类型,这就是创建了一个变量。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-1-25 02:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表