电脑用的时间久了,内存慢慢的就不够用,运行起来也会比较卡。与其想着加大电脑的内存,不如换一种思路,如何把电脑的内存释放出来。python3中的slots就是用来减少内存占用的,不过在使用的时候,小伙伴们知道需要注意哪些方面吗?小编今天把需要注意的地方都整理了出来,大家一起看看吧。
1.为什么 __slots__ 可以节省内存,提高速度的?
2.咋通过 __slots__ 来实现属性的存储与访问的?
3.使用了 __slots__ 的类怎么实现动态赋值,如果需要实例弱引用支持怎么搞?
4.使用了 __slots__ 的类继承与被继承时的表现?
针对这几个问题作答:
1. 通常情况下,类实例使用 __dict__来存储其属性数据,好处是允许我们在运行时动态的设置实例属性,然而 dict 哈希表本身的数据结构决定了它需要更多的内存,当创建的实例越多,或者实例的属性越多时,内存的耗费将更加严重。__slots__ 保证了解释器在编译时期就知道这个类具有什么属性,以分配固定的空间来存储已知的属性。
2.使用 __slots__ 时,会将属性的存储从实例的 __dict__ 改为类的 __dict__ 中:
>>>Y.__dict__ mappingproxy({'__module__':'__main__', '__slots__':('a','b'), '__init__':<function__main__.Y.__init__(self,a,b)>, 'a':<member'a'of'Y'objects>, 'b':<member'b'of'Y'objects>, '__doc__':None})
属性的访问是通过在类层级上为每个 slot 变量创建和 实现描述器(descriptor) 实现的,该描述器知道属性值在实例列表中的唯一位置。关于描述器与属性的访问在我的 走进 Python 类的内部 一文中均有详细的解释,感兴趣的同学可前去阅读。另外,这篇 how __slots__ are implemented 也许可以帮助你的理解,尽管我看它写于很多年前,但至今依然有借鉴意义。
3.怎么实现动态赋值和弱引用支持?答案是:在 __slots__ 中加上 __dict__ 和 __weakref__。
classY: __slots__=('a','b','__dict__','__weakref__') def__init__(self,a,b): self.a=a self.b=b >>>importweakref >>>y=Y(7,8) >>>y.a 7 >>>y.b 8 >>>y.c=9 >>>y.__dict__ {'c':9} >>>ry=weakref.ref(y) >>>ry <weakrefat0x107d17d68;to'Y'at0x107a4d480>
4.当类继承自一个未定义 __slots__ 的类时,实例的 __dict__ 和 __weakref__ 属性将总是可访问的。
classX: def__init__(self): self.a=7 classY(X): __slots__=('b','c') def__init__(self): super().__init__() self.b=8 self.c=9 >>>y=Y() >>>y.a 7 >>>y.b 8 >>>y.__dict__ {'a':7}
5.在父类中声明的 __slots__ 在其子类中同样可用。不过,子类将会获得 __dict__ 和 __weakref__,除非它们也定义了 __slots__ 。
classX: __slots__=('a','b') def__init__(self): self.a=7 self.b=8 classY(X): """没有定义__slots__""" classZ(X): __slots__=() >>>y=Y() >>>y.a 7 >>>y.b 8 >>>y.c=9 >>>y.__dict__ {'c':9} >>>z=Z() >>>z.a 7 >>>z.b 8 >>>z.c=9 AttributeError:'Z'objecthasnoattribute'c'
看来想要成功给电脑释放内存并不是一件容易的事情,这些常见的slots疑问点大家一定要牢记哦~更多Python学习推荐:PyThon学习网教学中心。