学习笔记(抽象基类、上下文管理、多态的应用、节约内存的实例)

学习笔记(抽象基类、上下文管理、多态的应用、节约内存的实例)

抽象基类

  • 什么是抽象类?
    • 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化.
  • 抽象类的作用
    • 从一堆类中抽取相同的内容,内容包括数据属性和函数属性。我的个人理解就是抽象基类就是一个框架模型。
  • 抽象基类的继承
    • 继承了抽象基类必须重写指定的方法。
import abc

class F_file(metaclass=abc.ABCMeta):
    all_type = 'file'
    @abc.abstractmethod #定义抽象方法
    def read(self):
        pass

    @abc.abstractmethod
    def write(self):
        pass

class TXT(F_file):
    def read(self):
        print('读txt文件')

    def write(self):
        print('写入到txt文件中')

a=TXT()
print(issubclass(TXT,F_file)) #True
print(isinstance(a,F_file)) #True
- 使用register方法注册。
import abc

class A(metaclass=abc.ABCMeta):
    all_title='file'

    @abc.abstractmethod
    def read(self):
        pass

    @abc.abstractmethod
    def write(self):
        pass

class B(object):
    pass

A.register(B)

print(issubclass(B,A)) #True

自定义一个类的案例

我们想自定义一种新类型的元组,对于传入的可迭代对象,我们只保留其中int类型且值大于0的元素。
例:

data = [12,-5,['tu',1],5,'8',1.1]
print(tuple(data))
#(12, -5, ['tu', 1], 5, '8', 1.1)
#新类型元组:
#new_tuple(data)  =>(12,5)

思路:继承元组并重写方法

class new_tuple(tuple):
	def __new__(cls, iterable):
		f = (i for i in iterable if isinstance(i,int) and i > 0 )
		return  super().__new__(cls,f)

print(new_tuple(data))

上下文管理

  • 同时包含 __enter__() 和 __exit__() 方法的对象就是上下文管理器。
    
  •   __enter__(self):进入上下文管理器自动调用的方法。	
    
  •  __exit__(self, exc_type, exc_value, exc_traceback):退出上下文管理器自动调用的方法
    
class Get_info():
	def __init__(self,name):
		self.name = name

	def __enter__(self):
		print('获取资源')
		return self.name  #将返回值作为as的对象
			
	def __exit__(self,exc_type,exc_val,exc_tb):
		print('错误类型:',exc_type)
		print('错误值:',exc_val)
		print('回溯错误:',exc_tb)
		return True #返回值为True时抛出错误但不会中断程序
		
with Get_info('lh') as f:
	print(f)

执行结果:

	获取资源
	lh
	释放资源
	错误类型: None
	错误值: None
	回溯错误: None

使用内置模块contextlib,@contextmanager让我们通过编写generator来简化上下文管理。

import contextlib

@contextlib.contextmanager
def show_info(name):
    #__enter__方法
    file_name = open(name,'r',encoding='utf-8')
	
	#yield
    try:
        yield file_name

    except Exception as err:
        print(err)

    #__exit__()方法
    finally:
        file_name.close()


with show_info('test.txt') as f:
    print(f.readline())

抽象基类的应用

import abc
import math
# from functools import total_ordering

# @total_ordering
class Shape(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def area(self):
        pass

    def __lt__(self, other):
        return self.area() < other.area()

    def __eq__(self, other):
        return self.area() == other.area()

class Cricle(Shape):
    def __init__(self,x):
        self.x = x
    def area(self):
        return self.x ** 2 * math.pi

class Square(Shape):
    def __init__(self,l):
        self.l = l

    def area(self):
        return self.l ** 2

class Rectange(Shape):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def area(self):
        return self.x * self.y

cricle=Cricle(5)
square=Square(6)
rectange=Rectange(4,9)

print(cricle < rectange)
print(square == rectange)

多态的应用

实现一个统一的获取面积的函数

import  math
class Cricle(object):
    def __init__(self,x):
        self.x = x

    def get_area(self):
        return self.x ** 2 * math.pi


class Rectange(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def get_area(self):
        return self.x * self.y

class Square(object):
    def __init__(self,x):
        self.x = x

    def get_area(self):
        return self.x ** 2

cricle=Cricle(5)
rectange=Rectange(7,6)
square=Square(7)

shape_list=[cricle,rectange,square]
for i in shape_list:
    print(i.get_area())

使用getattr方法实现

import  math
class Cricle(object):
    def __init__(self,x):
        self.x = x

    def get_area(self):
        return self.x ** 2 * math.pi


class Rectange(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y

    def get_Area(self):
        return self.x * self.y

class Square(object):
    def __init__(self,x):
        self.x = x

    def area(self):
        return self.x ** 2

def get_all_area(object):
    method_name = ['get_area','get_Area','area']
    for name in method_name:
        goal = getattr(object,name,None)
        if goal:
           return goal()

cricle=Cricle(5)
rectange=Rectange(7,6)
square=Square(7)

shape_list=[cricle,rectange,square]
area_list = list(map(get_all_area,shape_list))
print(area_list)

节约内存的实例

在游戏开发中,有一个玩家类Player,每有一个在线玩家,在服务器内则有一个player的实例,当在线的人数很多时,将产生大量实例(百万级)。
如何降低这些大量实例的内存开销?

  •    由于Python中默认用一个字典来保存一个对象的实例属性,使得我们在运行时可以任意设置新属性。如果创建成千上万个这样的小类,Python就会浪费掉很多内存,所以python中引入了 __slot__属性。这个属性的两个作用:1、给类指定一个固定大小的空间存放属性;2、无法给该类创建的实例添加新的属性。
    
#首先创建两个对象使用__dict__来查看对象内的内容
class Player1(object):
	pass

class Player2(object):
	__slot__ = ()
	pass

print(Player1.__dict__)
print(Player2.__dict__)

执行结果:

	{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Player1' objects>, '__weakref__': <attribute '__weakref__' of 'Player1' objects>, '__doc__': None}
	{'__module__': '__main__', '__slots__': (), '__doc__': None}

显而易见,使用__slot__()后,对象中的属性都由__slot__ : ()取代了。这时你可能是会说,虽然属性看着确实少了,但是没有说服力,那确实,下面我们拿数据来证明。
这里我需要调用tracemalloc模块来对内存使用进行跟踪

import tracemalloic

class Player1(object):    
    def __init__(self,name,uid,attribute=1,skill=2):
        self.name = name
        self.uid = uid
        self.attribute = attribute
        self.skill = skill

class Player2(object):    
	__slots__ = ('name','uid','attribute','skill')
    def __init__(self,name,uid,attribute=1,skill=2):
        self.name = name
        self.uid = uid
        self.attribute = attribute
        self.skill = skill
       
#内存跟踪
tracemalloc.start() #开始跟踪内存分配
player1 = [Player1('haha',1,) for i in range(100000)]  #size=15.3 MiB
# player2=[Player2('haha',1) for i in range(100000)] #size=7055 KiB

snapshot = tracemalloc.take_snapshot() #快照,当前内存分配
top = snapshot.statistics('filename')  #快照对象的统计  监控文件

for start in top:
    print(start)       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值