1. 元类
-
类:我们可以基于“类”创建出很多的“对象”。
-
动态创建类:有了一个“元类”就可以创建很多个“类”。
-
元类用途:可以动态创建类。
-
type():
- 可以查看对象的数据类型
- 可以使用type,动态创建类
- 语法:
类 = type(类名, (父类...), {属性, 方法})
# 创建一个默认父类,不包括任何属性方法的类
Person = type('Person', (), {})
# 是否可以用Person创建对象
p1 = Person()
print(p1)
# mro():父类是object
print(Person.mro())
# 传统方式创建父类Animal
class Animal():
def __init__(self,color):
self.color = color
def eat(self):
print("动物需要吃东西")
# 使用type动态创建一个类,父类就是Animal
def sleep(self):
print('狗在睡觉')
Dog = type('Dog', (Animal,), {'age':3,'sleep':sleep})
dog = Dog('Yellow')
print(dog.age)
dog.sleep()
# 是否继承了父类中的特性
print(dog.color) # 父类中的属性
dog.eat() # 父类中的方法
print(Dog.__name__)
2. 类装饰器的使用
- 【函数装饰器】https://blog.csdn.net/weixin_42375099/article/details/94644027#4__282
- 类装饰器:在不修改函数源代码的前提下,增加新的功能。
class AAA():
def __init__(self,func):
# print("我是AAA.init()")
self.__func = func
# TypeError: 'AAA' object is not callable
# 把新加的方法写在__call__属性中
def __call__(self, *args, **kwargs):
self.addFunc()
self.__func()
def addFunc(self):
print("用户权限验证")
print("日志系统处理")
@AAA
# TypeError: __init__() takes 1 positional argument but 2 were given
# test1 = AAA(test1)
def test1():
print("我是功能1")
test1()
- 实例对象test1不可以直接用函数的的方式来调用,必须在类中写 __ call __ ()方法;定义了__ call __()方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用。
3. 对象池
- 小整数池:[-5, 256];程序刚开始,一次性加载到内存。
- LGEB(局部变量,闭包中的变量,全局变量,内建变量)
- 大整数池:没每建一个不是小整数池的变量都会被自动存储在大整数池中。
- 字符串—intern机制:每个单词(字符串,下划线),不夹杂空格或者其他符号,默认开启intern机制,共享内存,考引用计数决定是否销毁。
4. 垃圾收集
-
垃圾回收机制(GC机制):在python中有两种回收机制
- 引用计算机制为主;隔代回收为辅
- 如何获取一个对象的引用计数:
sys.getrefcount()
(刚创建出来的对象引用计数为2)
-
增加引用计数的情况:
-
如果有新的对象使用该对象,+1
-
装进列表,+1
-
作为函数参数,+1
-
-
减少引用计数的情况:
- 新对象不再使用,-1
- 从列表中移除,-1
- 函数调用结束,-1
- del 显示销毁,-1
import sys
class AA():
# 创建对象开辟内存时调用
def __new__(cls, *args, **kwargs):
print("开辟内存空间")
return super(AA, cls).__new__(cls)
# 初始化方法
def __init__(self):
print("创建对象at:%s"%hex(id(self)))
# 对象被系统回之前,会调用该方法
def __del__(self):
print("%s say bye bye"%hex(id(self)))
def test1(aaa):
print(aaa)
print('a的引用计数为:%d'%sys.getrefcount(a))
a = AA()
print('a的引用计数为:%d'%sys.getrefcount(a))
b = a
print('a的引用计数为:%d'%sys.getrefcount(a))
list1 = [a]
print('a的引用计数为:%d'%sys.getrefcount(a))
test1(a)
print('a的引用计数为:%d'%sys.getrefcount(a))
print("*"*50)
-
隔代回收为辅:
-
原理:引用计数机制无法删除互相引用的对象;随着时间的推荐,程序冗余对象逐渐增多,到达一定的数量(阈值),系统进行回收。
-
代码:
import gc
gc.get_count()
gc.get_threshold()
:(700, 10, 10)
gc.set_threshold()
gc.disable()
import gc import time class AA(): def __new__(cls, *agrs, **kwargs): print('new') return super(AA,cls).__new__(cls) def __init__(self): print('object:born at %s'%hex(id(self))) def __del__(self): print('%s 被系统回收'%hex(id(self))) def start(): while True: a = AA() b = AA() a.v = b b.v = a del a del b time.sleep(0.5) print(gc.get_threshold()) print(gc.get_count()) start()
-