先上代码,

class C1(object):
    class_variable = 1


class C2(object):
    class_variable = []


object1 = C1()
object2 = C2()

print(C1.class_variable)
# 1
print(object1.class_variable)
# 1
object1.class_variable = 20
print(object1.class_variable)
print(C1.class_variable)
# 20
# 1

由此可见,在类变量为不可变变量(例子中为整数)时,对类C1产生的实例object1使用点运算更改object1的类变量后发现,

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

实例object1中的类变量产生了更改,而类C1中的类变量没有被更改。

这一点比较好理解。在类产生实例的同时,实例会从类中获取其内容的备份。因此,对实例进行修改,会更改实例中的内容而不会影响类中的内容。

要注意的是,当类变量是不可变变量时,遵循不可变变量的特性,实例中类变量的改变是将实例中的类变量指向一个新的内存地址。这点对理解之后的内容至关重要。

以下为测试,

class C1(object):
    class_variable = 1


class C2(object):
    class_variable = []


object1 = C1()
object2 = C2()


print(id(object1.class_variable))
print(id(C1.class_variable))
# 140719616585984
# 140719616585984

object1.class_variable = 20
print(id(object1.class_variable))
print(id(C1.class_variable))
# 140719616586592
# 140719616585984

 

那么,当类变量为可变变量时会怎样呢?

class C1(object):
    class_variable = 1


class C2(object):
    class_variable = []


object1 = C1()
object2 = C2()


print(object2.class_variable)
print(C2.class_variable)
# []
# []


object2.class_variable = [1, 2]
print(object2.class_variable)
print(C2.class_variable)
# [1, 2]
# []

在上面的代码中,使用了对object2的类变量直接赋值新列表的方式来更改类变量的数据,此时,object2中的类变量会指向一个新的内存地址,因此依然不会改变C2中的类变量的初始值。

但是,如果这样:

class C1(object):
    class_variable = 1


class C2(object):
    class_variable = []


object1 = C1()
object2 = C2()


print(object2.class_variable)
print(C2.class_variable)
# []
# []


object2.class_variable.append(1)
print(object2.class_variable)
print(C2.class_variable)
# [1]
# [1]

此时就会发现,当使用append函数对object2的类变量进行修改后,类C2中的类变量也神奇得被修改了!!

那么成因也可以归结为可变变量的特殊性。

我们先查一下两者的内存地址。

object2.class_variable.append(1)
print(id(object2.class_variable))
print(id(C2.class_variable))
# 1616354562632
# 1616354562632

没错,果然两者指向的内存地址是相同的。

这是因为,在使用append函数时,并不会改变实例object2的类变量的指向地址。因此,在更改该地址上列表的内容后,指向相同地址的类C2的类变量也一起被修改了。

在列表这个可变变量中,除了append函数,直接修改列表中的元素也会得到这样的结果,比如:

class C2(object):
    class_variable = [1, 2, 3]


object2 = C2()


object2.class_variable[1] = 20
print(object2.class_variable)
print(C2.class_variable)
# [1, 20, 3]
# [1, 20, 3]

 

那么,结论就是,当类变量为可变变量,并且实例在修改类变量时使用了不更改变量内存地址的方法对类变量进行了修改,此时是会同时影响类中的类变量的。

在日常应用中,在使用可变变量的类变量作为实例之间传递数据媒介时,修改实例中类变量的同时一定要切记检查是否会修改类中的类变量。

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄