python __slots__ .

python新模式的class,即从object继承下来的类有一个变量是__slots__,slots的作用是阻止在实例化类时为实例分配dict,默认情况下每个类都会有一个dict,通过__dict__访问,这个dict维护了这个实例的所有属性,举例如下
class base(object):
    v = 1
    def __init__(self):
          pass

b = base()
print b.__dict__
b.x = 2                     //可以增加新的变量
print b.__dict__
运行:
{}
{'x':2}
可见:实例的dict只保持实例的变量,对于类的属性是不保存的,类的属性包括变量和函数。由于每次实例化一个类都要分配一个新的dict,因此存在空间的浪费,因此有了slots,当定义了slots后,slots中定义的变量变成了类的描述符,相当于java,c++中的成员变量声明,类的实例只能拥有这些个变量,而不在有dict,因此也就不能在增加新的变量
class base(object):
   __slots__ = ('y')
    v = 1
    def __init__(self):
          pass

b = base()
print b.__dict__
b.x = 2              //error,不能增加新的变量 (任何试图创建一个其名不在__slots__中的名字的实例属性都将导致AttributeError异常)
print b.__dict__

注意,如果类的成员变量与slots中的变量同名,
class base(object):
    __slots=('y',)
   y = 2
    v = 1
    def __init__(self):
          pass

b = base()
print b.__dict__
b.x = 2
b.y = 3 //read only
print b.__dict__

目前的实现是该变量被设置为readonly!!!

Notes on using __slots__

  • Without a __dict__ variable, instances cannot be assigned new variables not listed in the __slots__ definition. Attempts to assign to an unlisted variable name raise an AttributeError. If dynamic assignment of new variables is desired, then add '__dict__' to the sequence of strings in the __slots__ declaration. (Changed in Python version 2.3)
  • Without a __weakref__ variable for each instance, classes defining __slots__ do not support weak references to its instances. If weak reference support is needed, then add '__weakref__' to the sequence of strings in the __slots__ declaration. (Changed in Python version 2.3)
  • __slots__ are implemented at the class level by creating descriptors ( 3.4.2.2) for each variable name. As a result, class attributes cannot be used to set default values for instance variables defined by __slots__; otherwise, the class attribute would overwrite the descriptor assignment.
  • If a class defines a slot also defined in a base class, the instance variable defined by the base class slot is inaccessible (except by retrieving its descriptor directly from the base class). This renders the meaning of the program undefined. In the future, a check may be added to prevent this.
  • The action of a __slots__ declaration is limited to the class where it is defined. As a result, subclasses will have a __dict__ unless they also define __slots__.
  • __slots__ do not work for classes derived from "variable-length" built-in types such as long, str and tuple.
  • Any non-string iterable may be assigned to __slots__. Mappings may also be used; however, in the future, special meaning may be assigned to the values corresponding to each key.

 

另外:

 由于在Python中不支持private这样的私有化修饰符,所以如果想把一个类属性置为私有的话,方法就是在属性名前加上双下划线__,这样在编译后,就可以起到保护私有属性的作用

    例如:

    

Python代码 复制代码 收藏代码
  1. 假如有个类Numstr有一个self.num属性   
  2.     在加上双下划线后变成self.__num后,经过编译就形成了self.__Numstr__num了,可以有效的保护私有属性,  
假如有个类Numstr有一个self.num属性
    在加上双下划线后变成self.__num后,经过编译就形成了self.__Numstr__num了,可以有效的保护私有属性,
Python代码 复制代码 收藏代码
  1. 但并非无懈可击,这只能算是一种保护机制  
但并非无懈可击,这只能算是一种保护机制

 

  同时在Python中提供了限制用户创建并未在类中定义的属性,方法是在类的定义后跟一个__slots__属性,它是一个元组,包括了当前能访问到的属性。例如:

   

Python代码 复制代码 收藏代码
  1. class test(object):   
  2.     __slots__=('foo');       //可以访问foo
  3.     foo=1.3;   
  4.        
  5. a=test();   
  6. print a.foo;   
  7. a.bar=15  
  8. print a.bar;   
  9.   
  10. 输出:  
class test(object):
    __slots__=('foo');    
    foo=1.3;
    
a=test();
print a.foo;
a.bar=15
print a.bar;

输出:
Python代码 复制代码 收藏代码
  1. 1.3  
  2. Traceback (most recent call last):   
  3.   File "D:\pythonEclipse\PythonStudy\src\Unit13\TestSlots.py", line 7in <module>   
  4.     a.bar=15  
  5. AttributeError: 'test' object has no attribute 'bar'  

另外:

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

test code

1#!/usr/bin/env python
2#_*_ coding:utf-8 _*_
3
4class test_slot(object):
5__slots__="width", "height"
6
7def width(self):
8print"width"
9
10
11class test(object):
12  def amethod(self):
13  print"amethod"

ipython执行代码导入

In [1]: from test import*
In [
2]: dir(test_slot)
Out[
2]:
[
'__class__',
'__slots__',
'__str__',
'height',
'width']

In [
3]: dir(test)
Out[
3]:
[
'__class__',
'__weakref__',
'amethod']

可以看到 test_slot 类结构里面已经有height和width属性了。

下面我们继续查看两个实例对象结构里都有什么吧

In [4]: s = test_slot()
In [
5]: t = test()

In [
11]: dir(s)
Out[
11]:
[
'__class__',
'__delattr__',
'__doc__',
'__slots__',
'height',
'width']

In [
12]: dir(t)
Out[
12]:
[
'__class__',
'__delattr__',
'__dict__',
'__doc__',
'amethod']

看到了吧, test_slot 的实例s 没有字典__dict__,多了__slots__属性,这样就不能任意绑定属性,只能绑定__slots__属性名称集合里的同名属性了。

我们来测试一把,先给两个实例的赋__slots__里面有的 height 属性,当然对t来说是新加属性。

In [7]: s.height = 1
In [8]: t.height = 0

赋值都没有问题。

下面再试一下不在__slots__里的属性名.

In [9]: s.abeen ="abeen"//和预期的一样,失败了。
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)

/home/abeen/learn_test/test/<ipython console>in<module>()

AttributeError:
'test_slot' object has no attribute 'abeen'

In [
10]: t.abeen ="abeen"//正常运行

posted on 2012-05-21 10:57  很多不懂呀。。  阅读(6171)  评论(0编辑  收藏  举报

导航