python学习2——类与对象深度问题,slots,with,类的比较,弱引用,getattr,map...

定义__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对象
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值