残局

不过在等杀死希望的最后一刀

0%

智障语言

没错,说的就是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:
# dosomething()
row_list = line.split(",")
if row_list[0] not in info_dict:
# dosomething()
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:
# dosomething()
row_list = line.split(",")
if row_list[0] not in info_dict:
# dosomething()
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 = {}
# dosomething()
row_list = line.split(",")
if row_list[0] not in info_dict:
# dosomething()
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,企图减少每行局部变量申请、释放内存造成的时间开销。

-------------感谢阅读有缘再见-------------