小明是个好孩子!python 面向对象:class 类的静态变量与实例变量
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__函数之外? - 类变量与实例变量的使用场景?