没错,说的就是Python!
话不多说,直接上场景。
简化场景
假定我有一个文件,这个文件包括某个年级某次考试的所有成绩,每行只有一个科目的成绩,需要将该场考试的成绩同步到数据库。现需要将某个人的成绩整合成json(方便生成数据库插入语句)
假定每行数据为:学号(数据库id),科目,成绩,班级(一些公有信息)。数据如下
1 2 3 4 5 6 7 8 9
| 1,chinese,90,class 2 1,math,88,class 2 1,englist,78,class 2 2,chinese,45,class 2 2,math,67,class 2 2,englist,37,class 2 3,chinese,57,class 1 3,math,85, class 1 3,englist,83,class 1
|
场景分析
大概就是根据学号创建两个哈希表,第一个哈希表用来存放某个人的成绩信息(读取每行时都需要修改),第二个哈希表用来个人数据信息(大部分一样 变动不大),代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| info_dict = {} score_dict = {} temp_dict = {} with open("src.txt") as f: lines = f.readlines() for line in lines: row_list = line.split(",") if row_list[0] not in info_dict: temp_dict["class"] = row_list[3] info_dict[row_list[0]] = temp_dict print(info_dict)
|
上面代码省略了第一个哈希表相关的操作,第二个哈希表在读取到新的学号时将个人信息相关数据构造成相关json
数据,最后再拼接两个json
,理论上没问题吧。上面这段代码运行结果如下:
1
| {'1': {'class': 'class 1'}, '2': {'class': 'class 1'}, '3': {'class': 'class 1'}}
|
正如写这篇文章的目的一样,结果并不符合预期。经测试发现,该种情况下的倒数第二行的赋值操作是引用传递。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| info_dict = {} score_dict = {} temp_dict = {} with open("src.txt") as f: lines = f.readlines() for line in lines: row_list = line.split(",") if row_list[0] not in info_dict: temp_dict["class"] = row_list[3] info_dict[row_list[0]] = temp_dict print(id(info_dict[row_list[0]])) """ 3082741301184 3082741301184 3082741301184 """
|
而当我把全局变量temp_dict
移动到每行的处理中时,它又神奇的变成了值传递。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| info_dict = {} score_dict = {} with open("src.txt") as f: lines = f.readlines() for line in lines: temp_dict = {} row_list = line.split(",") if row_list[0] not in info_dict: temp_dict["class"] = row_list[3] info_dict[row_list[0]] = temp_dict print(id(info_dict[row_list[0]])) print(info_dict) """ output: 2836819165048 2836821737616 2836820050496 {'1': {'class': 'class 2'}, '2': {'class': 'class 2'}, '3': {'class': 'class 1'}} """
|
这就是今天我要吐槽的点,你可以像C++那样什么都不管,让我自己去处理。但是你一会儿值传递、一会儿引用传递,给我胡乱处理算什么回事?
关于上述代码为什么要用全局变量temp_dict
存放,因为每日的数据量为几十G,企图减少每行局部变量申请、释放内存造成的时间开销。