当前位置: 首页 > 科技观察

解除了陷阱,却踏入了新的陷阱?

时间:2023-03-21 20:07:17 科技观察

相信很多人都知道Python有一个默认参数陷阱。函数的默认参数不能使用变量类型,否则运行结果会和你想的不一样。例如:这段代码运行时,如果传入了一个列表,将青楠和产品经理添加到列表中,用逗号连接打印。如果不传入参数,则打印产品经理庆南。好像没什么问题。但是如果不带参数跑几次,就会发现一个问题:为什么每次不传入参数,打印出来的结果都不一样?而且越来越长?这个原因我之前已经说过了公众号。根本原因是默认参数user_list=[]这里的默认值[]是在代码运行时(Runtime)初始化的,每次调用函数时都会用到。每次调用该函数时,都不会初始化同一个对象。解决这个问题也很简单,默认参数使用不可变对象即可:最近在古代码开发新函数,看到一个处理Exception的函数,默认参数使用的字典。代码大概是这样的:defconstruct_exception(param_dict={},msg='',extra_msg=''):"""下面是具体的代码"""所以顺手改了下:defconstruct_exception(param_dict=None,msg='',extra_msg=''):ifparam_dict=None:param_dict={}"""下面是具体的代码"""理论上我用这种方式去掉了一个隐患,具体以下面的代码来说,param_dict始终是一个字典,所以应该没有问题。结果,不久之后,有人向我报告了一个错误。我看了一下,不是我改的函数报错了吗?一桐分析了函数调用栈,找到了问题的原因。这个函数最初是这样写的:defconstruct_exception(param_dict={},msg='',extra_msg=''):"""somecode"""ifisinstance(param_dict,dict):msg=extra_msg.format(**param_dict)"""其他代码"""在古代码中,调用这个函数时,有两种写法:exception_msg=construct_exception(param_dict=None,msg='errormessage')param_dict={'code':123,'reason':'Databasereaderror'}exception_msg=construct_exception(param_dict=param_dict,extra_msg='错误代码为:{code},错误原因:{reason}')当他没有使用param_dict时parameter,他竟然主动传了一个Nonein。这样他传入的None就会被我转成一个空字典。所以代码会转到extra_msg.format(**param_dict)。这时候因为大括号里面的参数没有填,报错:这个新bug很好解决,然后判断param_dict是否为空:defconstruct_exception(param_dict={},msg='',extra_msg=''):"""Somecodes"""ifparam_dictandisinstance(param_dict,dict):msg=extra_msg.format(**param_dict)"""Othercodes"""这确实应验了那句话,当一块明显有问题的代码运行正常,你不应该碰它。它可能处于消极或积极状态,这种变化可能会使它出错。