前几天,运营反馈了一个BUG,某些数据在写入数据库后,其时间字段出现异常,与当前时间相差较多。
由于代码是不是我写的,所以开始一遍阅读代码一遍排查问题。
在主流程中,仅仅发现了一个对时间赋值的语句,并且赋值使用的是data.CreateTime=int(time.time())这样的形式,应该没有问题。
在别的地方没有找到对该字段赋值的操作,于是想看看这个类是不是自身有什么方法会修改时间字段。
最终在类初始化函数中找到了这样的内容
1 class Data(): 2 def __init__(a, b=None, CreateTime=int(time.time())): 3 self.a = a 4 self.b = b 5 self.CreateTime = CreatTime
问题就出现在这里,在Python官方文档中有这么一句话:
Default parameter values are always evaluated when, and only when, the “def” statement they belong to is executed.
https://docs.python.org/3/reference/compound_stmts.html
意思是,默认参数始终在且仅在函数定义时赋值一次,所以上面的代码造成的问题是,如果该类在实例化时没有传入Creatime参数,则其CreateTime参数会默认为程序启动的时间。
另外,如果参数默认值是可变对象,那么会出现另外一个问题,如果函数修改了这个对象,那么默认值也会被修改。
This is especially important to understand when a default parameter is a mutable object, such as a list or a dictionary: if the function modifies the object (e.g. by appending an item to a list), the default value is in effect modified.
如果写出了如下代码:
def f(a, L=[]): L.append(a) return L print f(1) print f(2) print f(3)
则其输出为:
[1] [1, 2] [1, 2, 3]
那么如何解决这个问题呢?
一般情况下,推荐的解决方式是,使用None作为参数的默认值,然后进行判断,如果发现参数为None,则重新对其进行赋值。
对于最开始的例子,解决之后的代码如下:
1 class Data(): 2 def __init__(a, b=None, CreateTime=None): 3 self.a = a 4 self.b = b 5 self.CreateTime = int(time.time()) if CreateTime is None else CreateTime
来源:https://www.cnblogs.com/ruizhang3/p/6720879.html