Python 高级编程技巧 第二讲 内置不可变类型并修改其实例化行为、slots属性、contextmanager上下文管理器、创建可管理对象属性、类比较操作

第二讲

一、如何派生内置不可变类型并修改其实例化行为

这里有一道练习题,我们想定义一个新类型的元组,对于传入的可迭代对象,我们只保留其中int类型并且值还要大于0.

或许我们可以这么写,尝试一下:

class Intuple(tuple):
	def __init__(self,iterable):
		tu = (i for i in iterable if isinstance(i,int) and i > 0)
		super().__init__(self,tu)

tu = Intuple([2,22,-1,['x','y'],'stupid',8])
print(tu)

但是结果不尽人意,创建失败:

TypeError: object.__init__() takes exactly one argument (the instance to initialize)

我们在这里需要考量一下缘由,tuple是内置不可变类型,对于它的new方法我们需要额外注意,我们来做一个试验:

tu = tuple.__new__(tuple,'abc')
print(tu)
tuple.__init__(tu,'abc')
print(tu)
--------------------------
结果:
('a', 'b', 'c')
('a', 'b', 'c')

在这里我们需要说明几点:

  1. 首先,如果我们去查阅tuple类的new方法,发现其内容如下:
    在这里插入图片描述
    这容易引起我们的误解,其实它的参数并未明确表达,倘若我们按照给定的文档内容去创建tuple对象,会报错:
tu = tuple.__new__(1,2,3)
-----------------------------
结果:
TypeError: tuple.__new__(X): X is not a type object (int)

反馈回的错误意思本人还未能明白,经过和老师的讨论知悉,这里的参数形式应该是这样的:

tu = tuple.__new__(tuple,iterable)

括号内前面的tuple就是告诉基类,具体哪个类在创建对象,这里是tuple类正在创建对象。这里的基类暂且不需要管它,是底层封装的类。后面的iterable意思试说明只能传入一个可迭代的对象

  1. 回归到一开始,我们把代码搬运过来:
tu = tuple.__new__(tuple,'abc')
print(tu)
tuple.__init__(tu,'abc')
print(tu)
--------------------------
结果:
('a', 'b', 'c')
('a', 'b', 'c')

结果表明,通过new方法且传入可迭代对象,就可以创建并返回一个元组了,init方法的初始化并不负责创建元组对象。
这就说明,一开始我们企图通过init魔法方法来定义新类型元组,是不可行的。

我们需要通过改写new方法来派生一个新类型的元组类:

class Intuple(tuple):
	def __new__(cls,iterable):
		f = [i for i in iterable if isinstance(i,int) and i > 0]
		return super().__new__(cls,f)
		
tu = Intuple([2,22,-1,['x','y'],'stupid',8])
print(tu)
-------------------------
结果:
(2, 22, 8)

二、如何为创建大量实例节省内存(__slots__属性)

现在有一个练习:
在游戏开发中,有一个玩家Player,每有一个在线玩家,在服务器内则有一个player的实例,当在线的人数很多的时候,将产生大量实例(百万级)。

如何降低这些大量实例的内存开销?

**这里要介绍一种的新的方法,定义__slots__属性。**它可以帮助我们减少内存的使用,原因接下来讲解:

案例代码如下:

class Player1(object):
	def __init__(self,uid,name,status):
		self.uid = uid
		self.name = name
		self.status = status

class Player2(object):
	__slots__ = ('uid','name','status')  # 将对象属性名传入
	def __init__(self,uid,name,status):
		self.uid = uid
		self.name = name
		self.status = status
#主程序入口
if __name__ == '__main__':
	p1 = Player1('1','Tom',1)
	p2 = Player2('2','Amy',1)
	
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值