生命周期指的是一个对象, 从诞生到消亡的过程
当一个对象被创建时, 会在内存中分配相应的内存空间进行存储
当这个对象不再使用, 为了节约内存, 就会把这个对象释放
如何监听一个对象的生命过程(例如何时被创建、何时消亡)?
方法 | 作用 | 应用 |
---|---|---|
__new__ 方法 | 当我们创建对象时, 用于给对象分配内存的方法 |
通过拦截这个方法, 可以修改对象的创建过程(如:单例设计模式) |
__init__方法 |
每个对象实例化的时候,会自动执行这个方法 |
可以在这个方法里面,初始化一些实例属性 |
__del__方法 |
当对象被释放的时候调用这个方法 |
可用于在这个方法中清理资源 |
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()
1)python中,万物皆对象,不存在基本数据类型
(在其他语言中,int、float、bool...为基本数据类型)
2)所有对象,都会在内存中开辟一块空间进行存储(可通过id()获取十进制内存地址)
3)对于常用的整数和短小的字符, Python会进行缓存处理
(提前就存储好了这些字符,使用他们时,会多次引用存储好的位置,而不是重新创建)
4)容器对象(如字典、列表、元组)存储的其他对象, 存储的并不是他们本身,而是对应地址
5)全局变量是由一个大字典进行引用,利用global()查看
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,所以不会被清除
1) 开启垃圾回收机制:import gc
gc.enable() 开启垃圾回收机制(默认开启)
gc.disable() 关闭垃圾回收机制
gc.isenabled() 判定是否开启
2) 达到了垃圾回收的阈值
垃圾回收器中, 新增的对象个数和释放的对象个数之差到达某个阈值
gc.collect() 执行一次垃圾回收(开关状态无效)
# 要求:做一个计算机,实现一些基本功能,加减乘除运算,以及打印结果
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)