python核心阶段(四)—— 生命周期方法、内存管理机制以及阶段案例

    生命周期指的是一个对象, 从诞生到消亡的过程
    当一个对象被创建时, 会在内存中分配相应的内存空间进行存储
    当这个对象不再使用, 为了节约内存, 就会把这个对象释放

1.监听对象生命周期

    如何监听一个对象的生命过程(例如何时被创建、何时消亡)?

方法 作用 应用
__new__ 方法

当我们创建对象时, 用于给对象分配内存的方法

通过拦截这个方法, 可以修改对象的创建过程(如:单例设计模式)

__init__方法
        

每个对象实例化的时候,会自动执行这个方法

可以在这个方法里面,初始化一些实例属性
__del__方法
 
当对象被释放的时候调用这个方法
    
可用于在这个方法中清理资源

  • 案例:创建一个Person类,打印一下当前这个时刻,由Person类产生的实例有多少个                      (创建+1,删除-1)
class Person:
    __count = 0  #把它当作类属性,而不是全局变量,封装更加完整;设置成类内部的私有属性,更加安全

    def __init__(self): #每当新建实例时,都会自动调用一次它
        Person.__count = Person.__count +1 #计数+1

    def __del__(self):#每当清理实例时,都会自动调用一次它
        Person.__count = Person.__count - 1 #计数-1

    @staticmethod   # 设置静态方法,不用实例就可以调用
    def number():
        print(f"当前的人数是{Person.__count}个")

p1 = Person()
del p1
p2 = Person()
Person.number()

2.内存管理机制

 2.1 存储方面

     1)python中,万物皆对象,不存在基本数据类型

             (在其他语言中,int、float、bool...为基本数据类型)                                                      

     2)所有对象,都会在内存中开辟一块空间进行存储(可通过id()获取十进制内存地址) 

     3)对于常用的整数和短小的字符, Python会进行缓存处理

            (提前就存储好了这些字符,使用他们时,会多次引用存储好的位置,而不是重新创建)  

     4)容器对象(如字典、列表、元组)存储的其他对象, 存储的并不是他们本身,而是对应地址  

     5)全局变量是由一个大字典进行引用,利用global()查看
      

 2.2 垃圾回收方面

    2.2.1 引用计数器

     一个对象, 会记录着自身被引用的个数

     作用:当引用个数变为0时,该对象就会被当作 “垃圾” 清理掉

     查看引用个数语法:   import sys
                                        sys.getrefcount(对象)     注意:在使用该语法时,也引用了一次对象,+1

  • 引用计数器加减场景
情况 语法实例
引用计数 +1 创建对象 p1 = Person()
引用对象 p2 = p1
对象作为函数参数

log(p1)

这里注意会+2, 因为内部有两个属性引用着这个参数

对象作为元素,存储在容器中 l = [p1]
引用计数 -1 对象的变量名被显式销毁 del p1
对象的变量名被赋予新的对象 p1 = 123
一个对象离开它的作用域 一个函数执行完毕时
    内部的局部变量关联的对象, 它的引用计数就会-1
对象所在的容器被销毁,或从容器中删除对象

    2.2.2 垃圾回收机制

     作用:从经历过"引用计数器机制"仍未被释放的对象中, 找到"循环引用", 清除相关对象

     循环引用问题:在产生了循环引用情况之后,对象引用个数至少是1,所以不会被清除

  • 循环引用说明
python核心阶段(四)—— 生命周期方法、内存管理机制以及阶段案例_第1张图片 循环引用案例说明

  • 垃圾回收时机(应用) —— 自动回收

       1) 开启垃圾回收机制:import gc

                gc.enable()    开启垃圾回收机制(默认开启)
                gc.disable()    关闭垃圾回收机制
                gc.isenabled()    判定是否开启

        2) 达到了垃圾回收的阈值

                垃圾回收器中, 新增的对象个数和释放的对象个数之差到达某个阈值

  •  垃圾回收时机(应用) —— 手动回收

                gc.collect()     执行一次垃圾回收(开关状态无效)

3.小节案例:针对核心阶段(一)~(四)

  • 要求:做一个计算机,实现一些基本功能,加减乘除运算,以及打印结果
# 要求:做一个计算机,实现一些基本功能,加减乘除运算,以及打印结果
import win32com.client

class Caculator:

    def __say(self,word): #语音播报方法
        speaker = win32com.client.Dispatch("SAPI.SpVoice")  # 语音播报系统
        speaker.Speak(word)

    def __getzsq(word = ""):# 默认值为空字符串   
        """
        定义了一个含参的装饰器
        主要作用:根据不同的运算符号进行播报
        """
        def __say_zsq(func):
            def inner(self, n):
                speaker = win32com.client.Dispatch("SAPI.SpVoice")  # 语音播报系统
                speaker.Speak(word + str(n))
                return func(self, n)
            return inner
        return __say_zsq

    def __check_zsq(func):
        """
        定义了一个装饰器,主要负责进行容错处理
        如果数据类型不是int类,则报错
        """
        def inner(self,n):
            if not isinstance(n, int):
                raise TypeError("当前这个数据的类型有问题,应该是一个整型(int)数据")  # raise:抛出错误
            return func(self,n)
        return inner

    @__check_zsq
    @__getzsq()
    def __init__(self, num): # 创建类时自动调用,生成result属性初值
        self.__result = num  # 把result定义为对象属性,
                             # 这是因为result为类属性时,类属性只有一个,在多次运算同时进行时,可能出错

    @__check_zsq
    @__getzsq("加")
    def jia(self,n):#加法
        self.__result += n
        return self

    @__check_zsq
    @__getzsq("减")
    def jian(self,n):#减法
        self.__result -= n
        return self

    @__check_zsq
    @__getzsq("乘")
    def cheng(self,n):#乘法
        self.__result *= n
        return self

    @__check_zsq
    @__getzsq("除以")
    def cheng(self, n):#除法
        self.__result *= n
        return self

    def show(self): #对结果进行播报,展示
        self.__say(f"计算的结果是:{self.__result}")
        print(f"计算的结果是:{self.__result}")
        return self

    @property #可以将方法像变量一样调用
    def result(self): #result为私有属性,所以设置一个函数专门调用它
        return self.__result

c1 = Caculator(2)
c1.jia(6).jian(4).cheng(5).show() # 在上述每一个方法中加入return,可以实现链式

print(c1.result)

你可能感兴趣的:(python核心阶段,python学习笔记,python,学习方法)