小明是个好孩子!python 面向对象:class 类的静态变量与实例变量

2023年 7月 12日 26.7k 0

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__函数之外?
    • 类变量与实例变量的使用场景?

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论