区分类属性和对象属性
(1)类属性:
- 属于类的属性, 可以通过(类名. ) 的方式调用.
(2)对象属性:
- 属于对象的属性, 可以通过 (对象名. ) 或者 (self. )的形式调用.(一个是在外部调用(前),一个是在内部调用(后)
举一个例子
1. 定义手机类, 属性: 品牌(brand), 颜色(color).
class Phone:
# 设置类属性
made_address = '中国' # 写到函数外的属性, 就是: 类属性, 即: 属于类的, 能被该类下所有的对象所共享.
# 设置属性.
def __init__(self) -> None:
self.brand = "华为" #这里就是对象属性,在类中方法/函数的内部
这里的区别就是同样打印made_address
- 通过类调用类属性:print(Phone.made_address)
- 通过对象调用类属性:p = Phone() => print(p.made_address) 需要两步
我们推荐第一种
看到这里有人问了,然后呢,后面才是最容易混淆的地方
我们先看代码最下面打印的结果(#号后面的部分),你能想明白么?
class Person:
# 记录创建对象数
count = 0
# 初始化实例, 给定name和age属性, 创建一个实例count加1
def __init__(self, name, age):
self.name = name
self.age = age
Person.count += 1
self.count += 3
def __del__(self):
Person.count -= 1
self.count -= 2
print("删除了", Person.count, self.count) #第一次:删除了 1 2 第二次:0 3
a = Person('小明', 21)
b = Person('小红', 20)
print(Person.count, a.count, b.count) # 2, 4, 5
print("结束了么")
'''
运行之后的答案是:
2 4 5
2 4
结束了么
删除了 1 2
删除了 0 3
'''
好,接下来我们一起来分析一下
根据代码自上而下的顺序,我们知道:
实例了一个对象a,那么__init__函数直接执行,因为他是在创建对象的时候自动运行,
所以此时:count=0 经过 Person.count += 1 之后变成了 1
类属性中 的值变成了 1
同样,定义了一个b,原先的类属性中的值是1 ,经过Person.count += 1 之后变成了 2。
这就是为什么打印的 Person.count 结果是2
然后我们再看一下为什么a.count=4:
首先实例化a之后,count这个类属性是1,有同学就问了:为什么会一个self.count会调用类属性呢,这里的原则是这样的,当自己所在的方法中没有对应 的属性,他会到类中去找,然后拿到自己的方法中去用,这就是为什么是1+3=4了
然后我们再看一下为什么b.count=5:
其实跟上面一样,只是这里我们实例化b之前已经实例化了a,也就是类属性中的count经过两次Person.count += 1之后变成了2 ,就得到2+3=5的答案
那__del__函数那里是怎么进行的呢:
首先我们应该知道的是这个函数是在什么时候执行,有的同学会说不就是调用完么,这里是混淆的最大的一点,这个函数一是在是在所有程序结束后在内存中删除对象的时候调用的,二是在用del 对象 的方式进行调用的(请看上面的代码最后的部分,‘结束了么’不是最后打印的)。
然后第一次的1 、2怎么来的呢:
其实此时我们的count经过2次的+1变成了2,这个时候我们再-1,就变成了1;
self.count我们不是已经得出了来了是4,这里我们4-2=2
第二次的0、3呢:
count现在是1,我们经过对类属性-1=0
self.count对于b这个对象我们得出来的是5,所以得出5-2=3
就得到上面的所有结果