• python 面向对象(其三)


    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,这种变量形式就叫做静态变量,也叫做类变量。

    类变量的定义和使用必须有两个要点:

    1. 定义类变量时,必须在def __init__()函数之外;
    2. 类变量的使用必须为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__函数之外?
    • 类变量与实例变量的使用场景?
  • 相关阅读:
    syslog
    setting-url配置
    计划任务_crontab
    css
    git之一: git基础
    LeetCode 第 151 场周赛
    LeetCode 第 149 场周赛
    LeetCode 第 150 场周赛
    【解决方案】SpringCloud项目优雅发版、部署
    NAT(地址转换技术)学习
  • 原文地址:https://www.cnblogs.com/SilenceCity/p/pythonOO3.html
Copyright © 2020-2023  润新知