测试代码:
class A:
x = []
y = 0
z = ''
def __init__(self):
#self.x=[]
#self.y=0
#self.z=''
pass
def add(self):
self.x.append('1')
self.y+=1
self.z+='1'
a=A()
print (a.x,a.y,a.z,id(a.x),id(a.y),id(a.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
b=A()
print (b.x,b.y,b.z)
print (A.x,A.y,A.z)
a.add()
print (a.x,a.y,a.z,id(a.x),id(a.y),id(a.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
b.add()
print (b.x,b.y,b.z,id(b.x),id(b.y),id(b.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
输出:
[] 0 2143136050752 140710602131072 2142814937840
[] 0 2143136050752 140710602131072 2142814937840
[] 0
[] 0
[‘1’] 1 1 2143136050752 140710602131104 2142816448816
[‘1’] 0 2143136050752 140710602131072 2142814937840
[‘1’, ‘1’] 1 1 2143136050752 140710602131104 2142816448816
[‘1’, ‘1’] 0 2143136050752 140710602131072 2142814937840
在python定义列表型类变量时如果没有对其初始化,即没有部署其对应的实例变量,就会出现类变量与实例中的变量同步变化的情况。
而这种情况在其他类型的数据,如实数型和字符串型的变量上就不会出现。
原因修改后的代码:
class A:
x = []
y = 0
z = ''
def __init__(self):
self.x=[]
self.y=0
self.z=''
#pass
def add(self):
self.x.append('1')
self.y+=1
self.z+='1'
a=A()
print (a.x,a.y,a.z,id(a.x),id(a.y),id(a.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
b=A()
print (b.x,b.y,b.z)
print (A.x,A.y,A.z)
a.add()
print (a.x,a.y,a.z,id(a.x),id(a.y),id(a.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
b.add()
print (b.x,b.y,b.z,id(b.x),id(b.y),id(b.z))
print (A.x,A.y,A.z,id(A.x),id(A.y),id(A.z))
输出:
[] 0 2503856091328 140710626772608 2503401874160
[] 0 2503856091264 140710626772608 2503401874160
[] 0
[] 0
[‘1’] 1 1 2503856091328 140710626772640 2503402336560
[] 0 2503856091264 140710626772608 2503401874160
[‘1’] 1 1 2503409909184 140710626772640 2503402336560
[] 0 2503856091264 140710626772608 2503401874160
这样的结果才是正常的。
经过对比两个输出结果,不难发现,在构建实例a时,加入了初始化操作,才会为列表变量x分配新的内存空间,若没有这步初始化,在后续对其进行append()操作后也不会改变其类变量和实例中变量的内存地址,它们始终占用一块内存。
这实际与python的内存管理机制有关,在对一个列表进行append(),extend()或+=等操作时,并不会改变这个列表的地址。因此,在上述未初始化代码中,add()操作始终是在对同一个列表操作,这就导致了类列表变量会与实例对象中的列表对象同步变化。
但是,为什么实数型变量y即使没有初始化,也始终正常呢?
再次观察两次结果,可以发现,实例化对象中的变量y无论是否初始化,在add()操作前,都指向同一块地址。这实际也是python内存管理的一个特性,对于实数、字符串这种占用内存较小的变量类型会根据值为其分配内存。也就是因为这个原因,使得在实例对象中改变变量的值后,该对象所拥有的该变量内存地址发生了变化,但是在类中,该简单变量依旧指向最初的地址。
python初学者,如有错误疏漏,敬请指正!



