类和对象深度问题解决技巧

类和对象深度解决技巧

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

  • 需求:自定义一中新类型的元组,对于传入可迭代对象,我们只保留其中的int类型并且值大于0的元素
    定义inttuple类
print(tuple([-1,2,-3,0]))# 将列表强制类型转换成元组
class inttuple(tuple):
    # 重写了父类的构造方法
    def __new__(cls,iterable):
        # iterable里面的元素大于0并且为整数的值
        f = [i for i in iterable if isinstance(i,int) and i > 0]# 列表推导式
        #for i in iterable:
        #    if isinstance(i,int) and i > 0:
        return super().__new__(cls,f)
        '''
        说明元组对象在__init__的构造方法之前就已经创建好了
        '''
a = inttuple([2,-2,'hajj',['h','j'],7])
print(a)
(-1, 2, -3, 0)
(2, 7)

__new__方法

1.__new__方法是创建对象的方法

  • 此处重写了父类的方法
  • 需调用父类的__new__方法创建对象
  • 需将对象返回出来给__init__方法
    2.__init__方法为初始化方法
  • 注意:当创建完对象时自动调用它
class Demo(object):
    def __new__(cls,*args,**kwargs):
        print('__new__')
        return object.__new__(cls)

    def __init__(self):
        print('__init__')
'''
__new__()方法在__init__()方法之前
__new__()方法可以创建一个对象
__init__()方法是在创建对象之后自动调用的一个方法
说明只有当__new__()方法创建好对象并且将对象进行返回才会自动触动__init__()构造方法
'''
d = Demo()
d = Demo.__new__(Demo)# 创建对象
Demo.__init__(d)# 初始化
__new__
__init__
__new__
__init__
'''
列表和元素的创建方式
'''
print(list('abs'))
li = list.__new__(list,'hajj')    
print(li)
list.__init__(li,'d fa')
print(li)
print(tuple('1234'))
tu = tuple.__new__(tuple,'123')
print(tu)
'''
体现了元组对象在__new__方法中就已经创建了
'''
'''
在创建tuple()的时候去添加过滤条件而已
'''
['a', 'b', 's']
[]
['d', ' ', 'f', 'a']
('1', '2', '3', '4')
('1', '2', '3')

列表推导式

  • 创建一个列表,并且将0到9这十个数字添加到列表中
li = []
for i in range(10):
    print(i)
    if  i % 2 == 0:
        li.append(i)
[0, 2, 4, 6, 8]

因为上述代码过多,考虑使用列表推导式

print([i for i in range(10) if i % 2 == 0])
[0, 2, 4, 6, 8]
for i in range(10):
    for j in range(10):
        print(i,j)
print([(i,j) for i in range(10) for j in range(10)])

内存消耗

import sys
import tracemalloc
class Player(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 = Player('1','sige',1)
    p2 = Player2('2','hjk',1)
    print(dir(p1))
    print(dir(p2))
    print(len(dir(p1)),len(dir(p2)))
    '''
    集合可以有减法表示差集
    __weakref__弱引用
    __dict__动态绑定属性
    '''
    print(set(dir(p1)) - set(dir(p2)))
    print(p1.__dict__)
    # 动态为p1添加属性
    p1.__dict__['level'] = 1
    print(p1.__dict__)
    # 动态为p1删除属性
    del p1.__dict__['level']
    print(p1.__dict__)
    print(sys.getsizeof(p1.__dict__))
    # print(p2.__dict__)# 报错,没有__dict__属性
    # p2.level = 1# 不可以动态绑定属性
    # p2.__slots__ = (1,)# 报错,只读模式
    '''
    p2不可以动态绑定属性,这时因为__slots__
    '''
    '''
    跟踪内存消耗
    '''
    tracemalloc.start()# 开始跟踪内存分配
    pla_1 = [Player(1,2,3) for i in range(10000)]# __dict__相当于用空间换取了时间
    pla_2 = [Player2(1,2,3) for i in range(10000)]
    snapshot = tracemalloc.take_snapshot()# 拍摄快照,当前的内存分配
    top = snapshot.statistics('filename')# 快照对象统计,监测文件
    for start in top[:10]:
        print(start)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'status', 'uid']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'name', 'status', 'uid']
29 28
{
    
    '__dict__', '__weakref__'}
{
    
    'uid': '1', 'name': 'sige', 'status': 1}
{
    
    'uid': '1', 'name': 'sige', 'status': 1, 'level': 1}
{
    
    'uid': '1', 'name': 'sige', 'status': 1}
368
E:\code\代码\python\python代码\demo.py:0: size=2436 KiB, count=39977, average=62 B
d:\visual studio 2019\common7\ide\extensions\microsoft\python\core\debugpy\_vendored\pydevd\pydevd.py:0: size=1956 B, count=13, average=150 B
d:\visual studio 2019\common7\ide\extensions\microsoft\python\core\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py:0: size=472 B, count=1, average=472 B
D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\threading.py:0: size=440 B, count=8, average=55 B
d:\visual studio 2019\common7\ide\extensions\microsoft\python\core\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_trace_dispatch_regular.py:0: size=348 B, count=5, average=70 B

猜你喜欢

转载自blog.csdn.net/qq_45671732/article/details/109059599