Python中类属性和实例属性的区别

2022-10-20 14:49:21

1:下面这段代码,通过对象.类属性,对象.实例属性,还是类.类属性都没有问题

class experment(object):
    a = 1 # 此处为类属性
    def __init__(self, value):
        self.b = value #此处为实例属性
    def fuc(self):
        print(self.b)

e1 = experment(100)    #创建对象

print(e1.a)
print(e1.b)
print(experment.a)

1
100
1

但是当加入如下代码:

print(experment.b)

AttributeError: type object 'experment' has no attribute 'b'

则会报错,因为不能通过类名.属性名的方式去调用实例属性,当类实例化之后,只能实例对象去调用实例属性

2:下面进行如下操作,输出结果如下

experment.a += 1  #通过类名.类属性的方式去去修改类属性的值
print(e1.a)
print(experment.a)

2
2

我们再继续下面的操作

e1.a += 1   #通过对象.类属性的方式去修改类属性的值

print(e1.a)
print(experment.a)

2
1

看到没有,对象.类属性的值已经改变,而类名.类属性的值没有变化,Why???。。。这个其实挺简单的,解释下:

当我们使用实例对象名+类属性名,即 e1.a 的方式修改属性 a 的值时:相当于新建了一个 a 的副本,+1这个操作实际上是进行在这个 a 的副本上的,而当我们用类名+类属性名的方式调用 a 时,输出的其实是原封未动的类属性 a

类可以看成一间样板房,没有装修时,你家买的房子其实各项参数和样板房都是一样的,但是你在你自己家放了一把火,把自家房子烧了,管样板房么事?

3:接着说,在上面的代码上,我们不进行对a的任何重新操作,如下

class experment(object):
    a = 1 # 此处为类属性
    def __init__(self, value):
        self.b = value #此处为实例属性
    def fuc(self):
        print(self.b)

e1 = experment(100)    #创建对象

print(id(e1.a))
print(id(experment.a))

140703385523872
140703385523872

可以看到,其实这个时候类属性 a 的地址还是只有一块的,无论是通过对象,还是类的方式来调用,都调用的是一块内存上的数据

当我们加上如下代码

experment.a =2
print(id(e1.a))
print(id(experment.a))

e1.a = 3
print(id(e1.a))
print(id(experment.a))


140703385523904
140703385523904

140703385523936
140703385523904

发现,通过类+类属性的方式来修改类属性的值后, 并没有COPY出来一块 a 的地址,但是,当我们用对象+类属性的方式去修改类属性的值后,多出来一块 ‘a’。

总的来说,类和实例对象对于属性的修改权限其实就是作用域的问题,类有权限修改属性,而实例对象没有,于是,实例对象就在自己的内存范围内创建一个实例对象名+属性名的副本,调用的时候就是用的这个。

  • 作者:苏轼圈
  • 原文链接:https://blog.csdn.net/qq_41867145/article/details/107304112
    更新时间:2022-10-20 14:49:21