本文记录了我在使用Python的类时踩过的一个坑。
先不多说,直接上代码
class Test: # 创建一个Test类,其中有一个idk列表,初始值为0
idk= [0 for _ in range(3)]
d = {} # 创建一个空字典
for i in range(3): # 对字典中的每一个元素,赋予Test类的属性
d['obj'+str(i)] = Test()
for i in range(3): # 只对字典中每个对象的一个值进行赋值
d['obj' + str(i)].idk[i] = i+1
print(d['obj' + str(i)].idk)
for i in range(3): # 这里和上面的输出进行对比
print(d['obj' + str(i)].idk)
计算结果如下:
[1, 0, 0]
[1, 2, 0]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
输出结果分为两个循环,共6行。按照正常情况,两次循环输出的结果应该相同,但是我们发现,第二次循环的结果全部相同了。原因是按照上述代码对类中的列表进行定义时,没有经过初始化。每当你更改列表里的值时,所有类的对象中的该列表都会被更改,最后程序就会出现难以想象的错误。
解决方法就是在类中,对变量进行初始化定义,如下面的代码所示:
class Test: # 创建一个Test类,其中有一个idk列表,初始值为0
def __init__(self):
self.idk= [0 for _ in range(3)]
d = {} # 创建一个空字典
for i in range(3): # 对字典中的每一个元素,赋予Test类的属性
d['obj'+str(i)] = Test()
for i in range(3): # 只对字典中每个对象的一个值进行赋值
d['obj' + str(i)].idk[i] = i+1
print(d['obj' + str(i)].idk)
for i in range(3): # 这里和上面的输出进行对比
print(d['obj' + str(i)].idk)
结果输出如下:
[1, 0, 0]
[0, 2, 0]
[0, 0, 3]
[1, 0, 0]
[0, 2, 0]
[0, 0, 3]
最后总结与分析:
在一开始的代码中,我们实际上只是创建了一个类变量,类变量为类的所有实例(对象)所共有,只占用一份内存空间,所以当我们采用第一种 方式进行计算的时候,才会出现“一改全改”的现象
经过改进后,我们其实是把一开始的类变量变成了一个成员变量,每当该类创建一个实例对象时,就会有一个单独的成员变量与之对应,这也是我们一开始预想中的结果。
网友评论