Python实践105-__slots__变量

特殊变量__slots__

  • 用来限制类的合法实例属性名称,不遵守该限定时会引发AttributeError异常
  • 但实际使用时,往往被用来对内存和执行速度进行优化,使用了__slots__的类实例不再用字典来存储实例数据,而是使用 一种基于数组的更加紧凑的数据结构,在创建大量对象的程序中,使用__slots__会显著减少内存占用和执行时间
  • 如果类继承自使用__slots__的基类,那么它也需要定义__slots__来存储自己的属性,否则派生类的运行速度会更慢,占用内存也更多,比不使用__slots__还要糟糕
  • 没必要往__slots__添加方法,因为它们是存储在类中,而不是存储在每个实例中

限定属性的例子

class Student(object):
    __slots__ = ['name', 'age']

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.grade = 0


if __name__ == '__main__':
    try:
        s = Student('Li', 20)
    except Exception as e:
        print(e)
        # 'Student' object has no attribute 'grade'

节约内存的例子

  • 没有slots: noslot_mem: 203632640
import psutil
import os


class Student1(object):
    def __init__(self, name, age, id):
        self.name = name
        self.age = age
        self.id = id


if __name__ == '__main__':
    process = psutil.Process(os.getpid())
    mem_1 = process.memory_info().rss
    print('mem1:', mem_1)
    s = [Student1('python', 20, x) for x in range(1000 * 1000)]
    mem_2 = process.memory_info().rss
    print('mem2:', mem_2)
    print('noslot_mem:', mem_2 - mem_1)
  • 有slots: slot_mem: 98017280
import psutil
import os


class Student2(object):
    __slots__ = ['name', 'age', 'id']

    def __init__(self, name, age, id):
        self.name = name
        self.age = age
        self.id = id


if __name__ == '__main__':
    process = psutil.Process(os.getpid())
    mem_1 = process.memory_info().rss
    print('mem1:', mem_1)
    s = [Student2('python', 20, x) for x in range(1000 * 1000)]
    mem_2 = process.memory_info().rss
    print('mem2:', mem_2)
    print('slot_mem:', mem_2 - mem_1)

代码地址

本系列文章和代码已经作为项目归档到github,仓库地址:jumper2014/PyCodeComplete。大家觉得有帮助就请在github上star一下,你的支持是我更新的动力。什么?你没有github账号?学习Python怎么可以没有github账号呢,快去注册一个啦!