class 类的静态变量与实例变量
小明其实是一个内心柔软的孩子
--------------------------------------- 超人小明 --------------------属性---------------- 忍耐度: 小明对 每个人 的忍耐度都是有限的 崩溃值: 所有人 对小明的伤害达到顶点,小明就会崩溃 --------------------方法----------------
属性说明:
- 忍耐度:
- 每个人的忍耐度都是相互独立的,这取决于小明和自己的关系
- 崩溃值:
- 所有人对小明的伤害都是累加的,这个值是公共的
如上,在代码中标示为:
1 #! coding:utf-8 2 class XiaoMing: 3 4 crash_count = 0 5 crash_limit = 4 6 7 def __init__(self, relationship, person_limit): 8 self.relationship = relationship 9 self.person_limit = person_limit 10 self.person_count = 0 11 12 13 def goOut(self): 14 self.person_count += 1 15 if self.person_count < self.person_limit: 16 print("%s 忍耐次数 %s ,忍耐中..."%(self.relationship, self.person_count)) 17 else: 18 print ("%s 忍不了了!"%self.relationship) 19 20 XiaoMing.crash_count += 1 21 if XiaoMing.crash_count < XiaoMing.crash_limit: 22 print ("%s 崩溃忍耐次数 %s ,还没崩溃"%(self.relationship, XiaoMing.crash_count)) 23 else: 24 print ("%s 小明已经崩溃了"%self.relationship) 25 26 brother = XiaoMing("brother",3) 27 classmate = XiaoMing("classmate",2) 28 29 brother.goOut() 30 # ------------output---------------------# 31 # brother 忍耐次数 1 ,忍耐中... 32 # brother 崩溃忍耐次数 1 ,还没崩溃 33 classmate.goOut() 34 # ------------output---------------------# 35 # classmate 忍耐次数 1 ,忍耐中... 36 # classmate 崩溃忍耐次数 2 ,还没崩溃 37 classmate.goOut() 38 # ------------output---------------------# 39 # classmate 忍不了了! 40 # classmate 崩溃忍耐次数 3 ,还没崩溃 41 brother.goOut() 42 # ------------output---------------------# 43 # brother 忍耐次数 2 ,忍耐中... 44 # brother 小明已经崩溃了
这里我们注意到,XiaoMing.crash_count是每调用一次就全局增加1,这种变量形式就叫做静态变量,也叫做类变量。
类变量的定义和使用必须有两个要点:
def __init__()
函数之外;ClassName.classaVariable
另外,上面的实现方式,也可以用如下的方式来实现,效果是一样的,只是不常用
1 class XiaoMing: 2 crash_count = 0 3 ''' 4 省略其他代码 5 ''' 6 @classmethod 7 def boring(cls): 8 cls.crash_count += 1
类的实例变量与类变量之间交互影响
类变量与实例变量之间并不绝对隔离,也可以互相作用影响。具体例子见下面:
#! coding:utf-8 class XiaoMing: crash_count = 0 crash_limit = 4 def __init__(self, relationship): self.relationship = relationship def goOut2(self): XiaoMing.crash_count += 1 if XiaoMing.crash_count < XiaoMing.crash_limit: print ("%s 崩溃忍耐次数 %s ,还没崩溃"%(self.relationship, XiaoMing.crash_count)) else: print ("%s 小明已经崩溃了"%self.relationship) if __name__ == '__main__': brother = XiaoMing("brother",3) classmate = XiaoMing("classmate",2) #========================================== # 类变量也可以直接调用基本类进行修改 XiaoMing.crash_count = 5 print(classmate.crash_count) print(brother.crash_count) # -----------------output----------------- # 5 # 5 #========================================== # 也可以使用实例对象的class进行反射修改 brother.__class__.crash_count = 4 print(classmate.crash_count) print(brother.crash_count) # -----------------output----------------- # 4 # 4
但是实际上,instance.variable 并不完全等于 classname.variable;
在使用instance.classVariable进行直接赋值操作时,这个classVariable就被克隆成了一个临时的instanceVariable
如下:
1 #id()是用来查看变量指向的内存地址的;同一个变量使用的是同一个内存地址 2 print(id(brother.crash_count)) 3 print(id(brother.__class__.crash_count)) 4 brother.crash_count = 6 5 print(id(brother.crash_count)) 6 print(id(brother.__class__.crash_count)) 7 # -----------------output----------------- 8 # 4297644544 9 # 4297644544 10 # 4297644576 11 # 4297644544
如果上面概念没有完全理解的话,那么请看下面例子:
1 #========================================== 2 #但如果使用实例对象来赋值,则就会变为局部变量了。只对当前的实例对象有效,且不会影响到类变量的值 3 classmate.crash_count = 2 4 print(classmate.crash_count) 5 print(classmate.__class__.crash_count) 6 print(brother.crash_count) 7 classmate.goOut2() 8 print(classmate.crash_count) 9 # -----------------output----------------- 10 # 2 11 # 5 12 # 5 13 # classmate 小明已经崩溃了 14 # 2
思考与练习
- 为什么类变量一定要定义在
__init__
函数之外? - 类变量与实例变量的使用场景?