Python面向对象(三)
- Python对象的声明周期,以及周期方法
- 概念
- 涉及问题
- 监听对象生命周期
- 内存管理机制
Python对象的声明周期,以及周期方法
概念
指对象从诞生到消亡的过程
当一个对象被创建时,会在内存中分配相应的内存空间进行存储
当这个对象不再使用,为了节约内存,就会把这个对象释放
涉及问题
如何监听一个对象的生命过程?
Python如何掌控一个对象的生命?
监听对象生命周期
__new__方法
__init__方法
__del__方法
class Person:
# def __new__(cls, *args, **kwargs):
# print("拦截了")
def __init__(self):
print("初始化")
self.name="sz"
def __del__(self):
print("释放了")
pass
p = Person()
print(p)
print(p.name)
class Person:
__personCount =0
def __init__(self):
print("计数 + 1")
Person.__personCount += 1
# self.__class__.__personCount += 1 也可以
def __del__(self):
print("计数 - 1")
Person.__personCount -= 1
# self.__class__.__personCount -= 1 也可以
@classmethod
def log(cls):
print("当前人的个数是%d个"%Person.__personCount)
p = Person()
p2 = Person()
del p
Person.log()
# 计数 + 1
# 计数 + 1
# 计数 - 1
# 当前人的个数是1个
# 计数 - 1 # 因为最后会调用del释放空间
内存管理机制
- 存储方面
- 在Python中万物皆对象
- 所有对象都会在内存中开辟一块空间进行存储,会根据不同的类型以及内容,开辟不同不同的空间大小进行存储
返回该空间的地址给外界接收(称为"引用"),用于后续对这个对象的操作
可通过id()
函数获取内存地址(10进制)
通过hex()
函数可以查看对应的16进制地址
class Person:
pass
p = Person()
print(p)
print(id(p))
print(hex(id(p)))
# <__main__.Person object at 0x00000159A2287390>
# 1484484277136
# 0x159a2287390
- 对于整数和短小的字符,Python会进行缓存,不会创建多个相同对象
- 容器对象,存储的七大对象,仅仅是对其他对象的引用,并不是其他对象本身
- 垃圾回收方面
- 引用计数器
概念:一个对象,会记录着自身被引用的个数
每增加一个引用,这个对象的引用计数会自动+1
每减少一个引用,这个对象的引用计数会自动-1
查看引用计数
import sys
sys.getrefcout(对象) # 因为sys.getrefcout又引用了一次,所以会大一
#-----------------引用计算器-------------------
import sys
class Person:
pass
p1 = Person() # 1
print(sys.getrefcount(p1))
p2 = p1 # 2
print(sys.getrefcount(p1))
del p2
print(sys.getrefcount(p1)) # 1
del p1
print(sys.getrefcount(p1)) # NameError: name 'p1' is not defined
#-----------引用计数器机制-特殊场景-循环引用问题----------
# 内存管理机制 = 引用计数器机制 + 垃圾回收机制
# 当一个对象, 如果被引用 + 1, 删除一个引用: -1 0: 被自动释放
# 循环引用
# objgraph
# objgraph.count() 可以查看,垃圾回收器,跟踪的对象个数
import objgraph
class Person:
pass
class Dog:
pass
p = Person()
d = Dog()
print(objgraph.count("Person"))
print(objgraph.count("Dog"))
p.pet = d
d.master = p
# 删除p,d之后,对应的对象是否被释放
del p
del d
print(objgraph.count("Person"))
print(objgraph.count("Dog"))
# 1
# 1
# 1
# 1
# 并没有被释放,引用计数器的弊端
- 垃圾回收(引用计数器的扩展)
- 主要作用:从经历过“引用计数器机制”仍未被释放的对象中,找到“循环引用”,干掉相关对象
- 底层机制(难 没看懂)
- 垃圾回收时机
- 自动回收
# 1. 自动回收
# 开启垃圾回收机制
# gc.enable # 开启垃圾回收机制(默认开启)
# gc.disable # 关闭
# gc.isenabled # 判定是否开启
import gc
gc.disable()
print(gc.isenabled())
gc.enable()
print(gc.isenabled())
# 并且
# 达到了垃圾回收的阈值
# 垃圾回收器中,新增的对象个数和释放的对象个数之差达到某个阈值
# 涉及方法
# gc.get_threshold() 获取自动回收阈值
# gc.set_threshold() 设置自动回收阈值
print(gc.get_threshold())
- 手动回收
# 2. 手动回收
import objgraph
import gc
class Person:
pass
class Dog:
pass
p = Person()
d = Dog()
p.pet = d
d.master = p
del p
del d
gc.collect() #并不关心垃圾回收机制是否开启
print(objgraph.count("Person"))
print(objgraph.count("Dog"))