__slots__ & __weakref__

来源:互联网 发布:宠物狐狸 知乎 编辑:程序博客网 时间:2024/05/17 01:17

http://docs.python.org/release/2.7/reference/datamodel.html#slots
默认情况下,新旧类的实例都会使用一个dict来存储自身属性,在一定程度上会造成空间的浪费,尤其是在变量增多之后这种情况更加明显。
可以使用slots属性来阻止实例生成dict空间从而达到节省空间的目的。
下面分三种情况来讨论如何使用slots和定义或者重写slots属性后对实例产生的影响。

首先定义一般new-style class的方式:
In [1]: class A(object):
…: pass
…:
In [2]: a = A()
In [3]: a.dict # 该实例被自动分配了dict属性
Out[3]: {}
In [4]: a.b = ‘b’
In [5]: a.dict
在这个dict内维护了这个对象的变量
Out[5]: {‘b’: ‘b’}

第二种情况
In [1]: class A(object):
…: slots = ‘spam’ # 在这里定义我们的slots属性
…: def init(self): # 其他部分不变
…: pass
…:
In [2]: a = A()

In [3]: a.b = ‘b’ # 我们无法为A的实例添加新的变量

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.b = ‘b’
AttributeError: ‘A’ object has no attribute ‘b’

In [4]: a.dict # 该实例也没有dict属性,所以它不需要额外的空间来保存新的变量

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.dict
AttributeError: ‘A’ object has no attribute ‘dict

In [5]: a.spam # 同样的它没有spam属性,但是继续往下看

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.spam
AttributeError: spam

In [6]: a.slots # 我们在slots属性中指定了spam字符串
Out[6]: ‘spam’
In [7]: a.spam = ‘x’ # 我们不可以添加其他额外的变量,但是可以添加在slots中(可以是一个列表)所指定的字符串为名称的变量
In [8]: a.spam
Out[8]: ‘x’

第三种情况
In [1]: class A(object):
…: slots = ‘spam’
…: spam = ‘x’ # 我们在类的声明阶段创建一个和slots指定的字符串相同的变量
…: def init(self):
…: pass
…:
In [2]: a = A()

In [3]: a.dict # 同样没有分配dict属性

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.dict
AttributeError: ‘A’ object has no attribute ‘dict

In [4]: a.b = ‘b’ # 同样不能够创建新的变量

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.b = ‘b’
AttributeError: ‘A’ object has no attribute ‘b’

In [5]: a.spam # 查看我们在类的构造阶段创建的变量(属性)
Out[5]: ‘x’

In [6]: a.spam = ‘x’ # 不同的是不仅我们不能添加新的变量,当我们试图改变slots中的变量时会出发Attribute异常,并且该变量是read-only

AttributeError Traceback (most recent call last)
/root/Desktop/code/Learn/memleak/ in ()
—-> 1 a.spam = ‘x’
AttributeError: ‘A’ object attribute ‘spam’ is read-only

再来说说weakref

这是document中slots注意事项的第三条对weakref的说明:
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 version 2.3: Previously, adding ‘weakref’ to the slots declaration would not enable support for weak references.

然后我们借用老外的一个例子具体实现一下:

class K1(object):
slots = [] # Don’t support weak-refs….
class K2(object):
slots = ‘weakref’ # Do support weak-refs.

import weakref
k1 = K1()
k2 = K2()
weakref.ref(k1)
Traceback (most recent call last):
File “”, line 1, in
TypeError: cannot create weak reference to ‘K1’ object
weakref.ref(k2)

0 0
原创粉丝点击