定义__slots__节省内存
当一个类需要创建大量实例时,可以通过__slots__声明实例所需要的属性
举个例子,下面两个玩家类,Player1没有__slots__声明,Pyayer2有__slots__声明
class Player(object):
def __init__(self,uid,name,status):
# 由于没有__slots__声明,所以可以动态添加属性
self.uid = uid
self.name = name
self.status = status
class Player2(object):
__slots__ = ("uid","name","status")
# 限定Player2对象只能绑定uid,name和status属性,不能动态添加属性
def __init__(self, uid, name, status):
self.uid = uid
self.name = name
self.status = status
if __name__ == '__main__':
p1 = Player("1","ay",1)
p2 = Player2("2","tg",1)
# 动态添加属性,p2因为__slots__的原因不可以动态添加属性
p1.__dict__["level"]=1
利用tracemalloc
,跟踪内存消耗,看一下p1和p2的内存消耗对比
import tracemalloc
if __name__ == '__main__':
p1 = Player("1","ay",1)
p2 = Player2("2","tg",1)
tracelloc.start() # 开始追踪
# pla_1 = [Player(1,2,3) for i in range(10000)]
pla_2 = [Player2(1,2,3) for i in range(10000)]
snapshot = trancelloc.take_snapshot() #快照,当前内存分配
top = snashot.statistics('filename') #以文件形式进行追踪,监测文件
for start in top[:30]: # 不管这里的top取多长都无所谓
print(start)
两种方式一对比,差异就出来了。
with 上下文管理器
使用with的时候,需要和 enter 和exit搭配使用
class Demo(object):
def __enter__(self):
#在语句体之前运行
print("start")
return self
def test(self):
print("i am test")
def __exit__(self, exc_type, exc_val, exc_tb):
#在语句体之后运行
print("end")
with Demo() as d:
d.test()
使用装饰器,简化上下文管理器
import contextlib
@contextlib.contextmanager
def file_open(filename):
print("file open")
yield{}
print("file close")
with file_open("test.txt") as f:
print("file operation")
property
例子:设置age属性,若传入非int类型,则报错
class AgeDemo:
def __init__(self, age):
self.age = age
@property
def age_test(self):
return self.age
@age_test.setter
def age_test(self, age):
if not isinstance(age, int):
raise TypeError("TypeError")
self.age = age
a = AgeDemo(19)
print(a.age)
a.age_test = 20
print(a.age_test)
类进行比较操作
数字之间比较,比较的是大小关系
集合之前做比较,比较的是包含关系
函数名 | 意义 |
---|---|
gt | > |
ge | >= |
eq | = |
le | <= |
lt | < |
a = 2
b = 1
print(a.__gt__(b)) # gt >
print(a.__lt__(b)) # lt <
当数字或者集合之间做比较,会调用对应的方法。所以类之间也是需要使用这个方法来进行比较。
class Rect(object):
def __init__(self, w, h):
self.w =w
self.h = h
def area(self):
return self.w * self.h
def __str__(self):
return f"({self.w},{self.h})"
def __gt__(self, other):
return self.area() > other.area()
r1 = Rect(1,2)
r2 = Rect(3,4)
print(r1>r2) # 不会报错,因为会自动调用__gt__方法
需要添加,那么>=,<=,<都需要添加,很麻烦,所以这里可以使用装饰器total_ordering
from functools import total_ordering
#求矩形面积
@total_ordering
class Rect(object):
def __init__(self, w, h):
self.w =w
self.h = h
def area(self):
return self.w * self.h
def __str__(self):
return f"({self.w},{self.h})"
def __gt__(self, other):
return self.area() > other.area()
r1 = Rect(1,2)
r2 = Rect(3,4)
print(r1<=r2) # 不会报错,因为定义了装饰器,total_ordering已经把所有都绑定了
弱引用
weakref.ref()不占用引用次数
python中,万物皆对象,对象会占用引用计数,弱引用不占用引用计数。–
当引用计数为0时,对象会被自动释放,调用__del__
弱引用不占用引用计数
将弱引用改为引用
getattr
getattr(a,b,c) 相当于 a.b ,从a查找b方法,如果不存在,默认返回None,可以设置返回c
map(func, iterable)
将iterable中的元素 映射到func函数中处理,并返回新的map对象