类和对象深度问题及解决技巧
如何派生内置不可变类型并修改其实例化行为
=话不多说,上源码=
class IntTuple(tuple):
#重写父类方法
def __new__(cls, iterable):
# for i in iterable:
# if isinstance(i,int) and i>0:
#用列表推导式
f=[i for i in iterable if isinstance(i,int) and i>0]
return super().__new__(cls,f) #报错
i=IntTuple([2, -2, "jr", ["x", "y"], 4])
print(i)
- 说明 元组对象 再__init__构造方法之前 就已经创建好了,再创建tuple()的时候 加上过滤条件而已*
列表推导式
- 上代码就明白了
print([i for i in range(10) if i % 2 == 0])
如何为大量实例节省内存
我们知道,创建一个对象,就要给它分配内存,为什么可以节省内存呢,是用了__slot__魔法方法,下面看列子
#用之前
pla_1 = [Player(1,2,3) for _ in range(10000)] # size=1414 KiB __dict__非常消耗内存,以空间换取时间
#用之后
pla_2 = [Player2(1, 2, 3) for _ in range(10000)]#size=395 KiB
with 语句
- 以前是这么玩的
# try:
# print("123")
# raise KeyError
# except KeyError as e:
# print("KeyError")
# finally:
print("不论有无异常 都执行")
- 那现在呢
"""
可以用上下文管理器
"""
class Demo:
def __enter__(self):
print("start")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""
参数只有当异常时,才返回值
:param exc_type:异常类
:param exc_val:异常值
:param exc_tb:异常的跟踪信息
:return:
"""
print("end")
def test(self):
print("i am test")
with Demo() as d:
#调用__enter__
d.test()
#打印完所用内容调用__exit__方法,释放内存
或者,用@contextlib.contextmanager,一步到位,上下文管理器
propetrty管理对象属性
- 以前是这么玩的,
# #方法一
# #访问
# def get_age(self):
# return self.age
# #设置
# def set_age(self,age):
# if not isinstance(age,int):
# raise TypeError
# self.age=age
# age_pro=property(fget=get_age,fset=set_age)
- 那现在呢,装饰器优化
#方法二
@property
def age_test(self):
return self.age
@age_test.setter
def age_test(self, age):
if not isinstance(age,int):
raise TypeError
self.age=age
类之间比较操作
- @total_ordering
== 只要实现了任意两个大小关系,其他都是可以的,比如定义了r1>r2,那么r1<r2就不用写了==
"""
列子:⚪这个类 矩形面积与⚪的面积作比较
"""
import math
@total_ordering
class Circle:
def __init__(self,r):
self.r=r
def area(self):
return self.r**2*math.pi
def __gt__(self, other):
return self.area()>other.area()
def __ge__(self, other):
return self.area() >= other.area()
c=Circle(2)
# print(c.area())
r=Rect(2,2)