python 中的 __slots__ 的用法

在看sanic 源码时,发现在定义类的时候,会设置一个__slots__属性,由于之前没有用过个魔术变量,所以查了一下,这里记录一下该属性的作用。 我们知道,在python 的实例中,我们可以动态的给实例绑定属性与方法,像下面这样

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class Test:
    def __init__(self, name, age):
        self.name = name
        self.age = age

t = Test("yangyanxing", 18)
print(t.name, t.age)
# 给t 绑定一个city 属性
t.city = "BeiJing"
print(t.city)

我们在类中并没有定义city 属性,但是我们却可以给Test 实例添加一个city 属性,这个在python 中是被允许的。当然我也可以绑定方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
from types import MethodType


class Test:
    def __init__(self, name, age):
        self.name = name
        self.age = age


def show(self, msg):
    print(f"hello {self.name}, {msg}")


t = Test("yangyanxing", 18)
# 给t 绑定show 方法,这里需要使用MethodType
t.show = MethodType(show, t)
t.show("欢迎")

但是这种绑定是针对实例的,像上面的t 实例,如果再实例化另一个实例,它依然是没有city属性和show方法的。

但是有时候,我们并不希望给实例乱加属性与方法,或者我们想限制一下实例的属性与方法,只能设置我们规定的属性与方法,这时就可以通过 __slots__ 来限制

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from types import MethodType


class Test:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    __slotss__ = (
        "name",
        "age",
        "city",
        "show",
    )


def show(self, msg):
    print(f"hello {self.name}, {msg}")


t = Test("yangyanxing", 18)
print(t.name, t.age)
# 给t 绑定一个city 属性
t.city = "BeiJing"
# 给t 绑定show 方法
t.show = MethodType(show, t)
print(t.city)
t.show("欢迎")
t.school = "bjut"

这里的school 不在 __slots__ 里,所以这里会崩溃,不让设置。如果想要限制实例的属性,可以通过设置类的__slots__

但是子类不受限制,除非子类也设置了__slots__属性,子类如果也设置了__slots__属性,那么子类的属性限制是父类的slots加上自己的slots 之和