欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python 遇到的小坑

程序员文章站 2022-04-16 10:24:06
由于前端资源紧缺,我的后端系统迟迟等不来它的前端,没办法只好自己来写了。从html,js入门学起,然后照着vue.js的官方教程写了几个实例,从github上clone了一个不错的vue.js模版,填充了一个星期。虽然界面有些丑,但是总算是走通了全部的业务,期间被跨域,跳转,cookie等问题折磨得 ......

由于前端资源紧缺,我的后端系统迟迟等不来它的前端,没办法只好自己来写了。从html,js入门学起,然后照着vue.js的官方教程写了几个实例,从github上clone了一个不错的vue.js模版,填充了一个星期。虽然界面有些丑,但是总算是走通了全部的业务,期间被跨域,跳转,cookie等问题折磨得不要不要的。有时间的话,本螺旋手里剑会总结vue.js开发过程中遇到的问题。

言归正传,本周博主基本没碰python代码,只是修复了一个bug,这个bug很有意思。bug描述为:本次请求的返回结果中总是携带着之前请求的结果,重启服务后bug暂时修复,稍后又会出现。第一感觉是数据库缓存问题,但是我们没有对mysql启用特殊的缓存机制,所以不是缓存问题。第二感觉是执行相关的sql操作之后,结果是否commit立即生效,经过排查commit生效了,也不是这个问题。那就只好debug代码了,最后一个定位到了一个方法的传参问题。

展示问题代码的简化版本

#!/usr/bin/python
# -*- coding: utf-8 -*-


class TEST(object):
    def test(self, info, info_list=[]):
        info_list.append(info)
        return info_list


if __name__ == '__main__':
    a = TEST()
    print a.test(1)
    print a.test(2)
    print a.test(3)

相信大部分人和我对输出的预期是一样的,在写代码时,我认为输出结果是

[1]
[2]
[3]

但是实际的输出结果是

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

看来bug找到了,之前请求的info都保留在了这次请求的返回结果中。重启服务之后,info_list被重新初始化成[],所以bug短暂的消失了。问题找到了,但是为什么会产生这种问题呢。当我们实例化这个方法时,info_list被初始化为[],之后不会被再次初始化。可以理解为info_list在该方法中是一个全局变量,想修改它的值,只能在调用方法时传入一个新的info_list对其覆盖,也就是说将方法调用修改为a.test(1, [])就不会存在这种问题。并不是所有的数据结构都存在这个问题,只有list、dict这种可变的数据结构才会有这种问题,tuple、string、int等都不存在这个问题。所以说,以后在方法中对list、dict做初始化时建议使用一下风格。

 

#!/usr/bin/python
# -*- coding: utf-8 -*-


class TEST(object):
    def test(self, info, info_list=None):
        if info_list is None:
            info_list = []
        info_list.append(info)
        return info_list


if __name__ == '__main__':
    a = TEST()
    print a.test(1)
    print a.test(2)
    print a.test(3)

 

输出结果符合预期

 

 

[1]
[2]
[3]