您的位置是:网站首页>Python编程Python编程

为什么大佬的类都有__slots__?

少儿编程网2020-10-15 12:05:52Python编程 人已围观 来源:少儿编程 -用户投稿

简介如果你看过github当中一些大牛的代码,你会发现很多大牛经常在类的顶部加上__slots__关键字。如果你足够好奇,你可能会试着把这个关键字去掉再运行试试,你会发现去掉了之后什么也没有发生,一切依然运行得很好。那么这个__slots__关键字究竟是做什么的呢?它主要有两个功能,我们先来说第一个功能

s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

如果你看过github当中一些大牛的代码,你会发现很多大牛经常在类的顶部加上__slots__关键字。如果你足够好奇,你可能会试着把这个关键字去掉再运行试试,你会发现去掉了之后什么也没有发生,一切依然运行得很好。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

那么这个__slots__关键字究竟是做什么的呢?s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

它主要有两个功能,我们先来说第一个功能,就是限制用户的使用s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

我们都知道python是一门非常灵活的动态语言,很多在其他语言看起来完全不能容忍的事情在Python当中是可行的,这也是Python的设计理念,为了灵活和代码方便牺牲了效率。比如我们来看一个很简单的例子,由于Python是动态语言,所以类的成员甚至可以在类创建好了之后动态创建。这在静态语言当中是绝对不行的,我们只能调用类当中已有的属性,是不能或者很难添加新属性的。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

比如这段代码:s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

class Exp:
    def __init__(self):
        self.a = None
        self.b = None


if __name__ == "__main__":
    exp = Exp()
    exp.c = 3
    print(exp.c)

我们定义了一个类叫做Exp,我们为它创建了a和b两个成员。但是我们在使用的时候,对c成员进行了赋值。要知道Exp类当中是没有成员c的,但是程序并不会报错,我们这么运行了之后它会将c添加进这个实例当中。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

从一方面来看,这当然非常灵活,但是另一方面,这也留下了隐患。如果用户随意添加属性,可能会导致未知的问题,尤其在复杂的系统当中。所以有些时候为了严谨,我们会不希望用户做这种动态的修改。__slots__正是用来做这个的。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

我们把这个关键字加上,再来运行结果就不一样了:s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

class Exp:

    __slots__ = ['a', 'b']
    def __init__(self):
        self.a = None
        self.b = None


if __name__ == "__main__":
    exp = Exp()
    exp.c = 3
    print(exp.c)

如果你运行这段代码的话,你会得到一个报错,提示你Exp这个对象当中并没有c这个成员,也就是说我们只能运用__slots__这个关键字当中定义的成员,对于没有定义的成员不能随意创建,这样就限制了用户的使用。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

虽然现在大部分人使用这个关键字都是报着这个目的,但是很遗憾的是,Python创建者的初衷其实并不是这个。这就谈到了__slots__关键字的第二个作用,就是节省内存s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

如果了解过Python底层的实现原理,你会发现在Python当中为每一个实例都创建了一个字典,就是大名鼎鼎的__dict__字典。正是因为背后有一个字典,所以我们才可以创造出原本不存在的成员,也才支持这样动态的效果。我们可以人工地调用这个字典输出其中的内容,我们在加上__slots__关键字之前,输出的结果是这样的:s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

{'a': None, 'b': None}

但是加上了这个关键字之后,会得到一个报错,会告诉你Exp这个对象当中没有__dict__这个成员。原因很简单,因为使用dict来维护实例,会消耗大量的内存,额外存储了许多数据,而使用__slots__之后,Python内部将不再为实例创建一个字典来维护,而是会使用一个固定大小的数组,这样就节省了大量的空间。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

这个节省可不是一点半点,一般可以节省一半以上。也就是说牺牲了一定的灵活性,保证了性能。这一点也是__slots__这个关键字设计的初衷,但是现在很多人都用错了地方。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台


更多Python相关文章,请关注python自学网。s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台

来源:php中文网s14少儿编程网-Scratch_Python_教程_免费儿童编程学习平台


相关文章:

支持一下 ( )

为什么大佬的类都有__slots__?

      匿名评论
    • 评论
    人参与,条评论
    为什么大佬的类都有__slots__?

微信公众号

免费视频教程

先知道