slots 魔法

在 Python 中,我们在定义类的时候可以定义属性和方法。当我们创建了一个类的实例后,我们还可以给该实例绑定任意新的属性和方法。

看下面一个简单的例子:

  1. class Point(object):
  2. def __init__(self, x=0, y=0):
  3. self.x = x
  4. self.y = y
  5. >>> p = Point(3, 4)
  6. >>> p.z = 5 # 绑定了一个新的属性
  7. >>> p.z
  8. 5
  9. >>> p.__dict__
  10. {'x': 3, 'y': 4, 'z': 5}

在上面,我们创建了实例 p 之后,给它绑定了一个新的属性 z,这种动态绑定的功能虽然很有用,但它的代价是消耗了更多的内存。

因此,为了不浪费内存,可以使用 __slots__ 来告诉 Python 只给一个固定集合的属性分配空间,对上面的代码做一点改进,如下:

  1. class Point(object):
  2. __slots__ = ('x', 'y') # 只允许使用 x 和 y
  3. def __init__(self, x=0, y=0):
  4. self.x = x
  5. self.y = y

上面,我们给 __slots__ 设置了一个元组,来限制类能添加的属性。现在,如果我们想绑定一个新的属性,比如 z,就会出错了,如下:

  1. >>> p = Point(3, 4)
  2. >>> p.z = 5
  3. ---------------------------------------------------------------------------
  4. AttributeError Traceback (most recent call last)
  5. <ipython-input-648-625ed954d865> in <module>()
  6. ----> 1 p.z = 5
  7. AttributeError: 'Point' object has no attribute 'z'

使用 __slots__ 有一点需要注意的是,__slots__ 设置的属性仅对当前类有效,对继承的子类不起效,除非子类也定义了 __slots__,这样,子类允许定义的属性就是自身的 slots 加上父类的 slots。

小结

  • slots 魔法:限定允许绑定的属性.
  • __slots__ 设置的属性仅对当前类有效,对继承的子类不起效,除非子类也定义了 slots,这样,子类允许定义的属性就是自身的 slots 加上父类的 slots。

参考资料