python中的new-style class要求继承Python中的一个内建类型,一般继承object,也可以继承list或者dict等其他的内建类型。
在python新式类中,可以定义一个变量__slots__,它的作用是阻止在实例化类时为实例分配dict,

默认情况下每个类都会有一个dict,通过__dict__访问,这个dict维护了这个实例的所有属性,举例如下:

1 class base(object):  
2     var=9 #类变量  
3     def __init__(self):  
4         pass  
5   
6 b=base()  
7 print b.__dict__  
8 b.x=2 #添加实例变量  
9 print b.__dict__  

运行结果:
{ }
{'x': 2}
可见:实例的dict只保持实例的变量,对于类的属性是不保存的,类的属性包括变量和函数。
由于每次实例化一个类都要分配一个新的dict,因此存在空间的浪费,因此有了__slots__。
__slots__是一个元组,包括了当前能访问到的属性。
当定义了slots后,slots中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明,
类的实例只能拥有slots中定义的变量,不能再增加新的变量。注意:定义了slots后,就不再有dict。如下:

 1 class base(object):  
 2     __slots__=('x')  
 3     var=8  
 4     def __init__(self):  
 5         pass  
 6   
 7 b=base()  
 8 b.x=88 #添加实例变量  
 9 print b.x  
10 #b.y=99 #无法添加slots之外的变量 (AttributeError: 'base' object has no attribute 'y')  
11 #print b.__dict__ #定义了__slots__后,就不再有__dict__ (AttributeError: 'base' object has no attribute '__dict__')  

运行结果:

88
如果类变量与slots中的变量同名,则该变量被设置为readonly!!!如下:

 1 class base(object):  
 2     __slots__=('y')  
 3     y=22 # y是类变量,y与__slots__中的变量同名  
 4     var=11  
 5     def __init__(self):  
 6         pass  
 7       
 8 b=base()  
 9 print b.y  
10 print base.y  
11 #b.y=66 #AttributeError: 'base' object attribute 'y' is read-only  

运行结果:
22
22
Python是一门动态语言,可以在运行过程中,修改实例的属性和增删方法。一般,任何类的实例包含一个字典__dict__,
Python通过这个字典可以将任意属性绑定到实例上。有时候我们只想使用固定的属性,而不想任意绑定属性,
这时候我们可以定义一个属性名称集合,只有在这个集合里的名称才可以绑定。__slots__就是完成这个功能的。

 1 class test_slots(object):  
 2     __slots__='x','y'  
 3     def printHello(self):  
 4         print 'hello!'  
 5   
 6 class test(object):  
 7     def printHello(self):  
 8         print 'hello'  
 9   
10 print dir(test_slots) #可以看到test_slots类结构里面包含__slots__,x,y  
11 print dir(test)#test类结构里包含__dict__  
12 print '**************************************'  
13 ts=test_slots()  
14 t=test()  
15 print dir(ts) #可以看到ts实例结构里面包含__slots__,x,y,不能任意绑定属性  
16 print dir(t) #t实例结构里包含__dict__,可以任意绑定属性  
17 print '***************************************'  
18 ts.x=11 #只能绑定__slots__名称集合里的属性  
19 t.x=12 #可以任意绑定属性  
20 print ts.x,t.x  
21 ts.y=22 #只能绑定__slots__名称集合里的属性  
22 t.y=23  #可以任意绑定属性  
23 print ts.y,t.y  
24 #ts.z=33 #无法绑定__slots__集合之外的属性(AttributeError: 'test_slots' object has no attribute 'z')  
25 t.z=34 #可以任意绑定属性  
26 print t.z   

 

运行结果:
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'printHello', 'x', 'y']
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']
**************************************
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'printHello', 'x', 'y']
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printHello']
***************************************
11 12
22 23
34

正如上面所说的,默认情况下,Python的新式类和经典类的实例都有一个dict来存储实例的属性。这在一般情况下还不错,而且非常灵活,
乃至在程序中可以随意设置新的属性。但是,对一些在”编译”前就知道有几个固定属性的小class来说,这个dict就有点浪费内存了。
当需要创建大量实例的时候,这个问题变得尤为突出。一种解决方法是在新式类中定义一个__slots__属性。
__slots__声明中包含若干实例变量,并为每个实例预留恰好足够的空间来保存每个变量;这样Python就不会再使用dict,从而节省空间。

 

引用自:https://blog.csdn.net/sxingming/article/details/52892640#