相信不少 Python 开发者都听说过 __slots__,知道它可以帮助节省内存。但你是否思考过它背后的原理,以及在实际开发中的其他妙用?让我们一起深入探讨。...__dict__ 的开销在 Python 中,普通类的实例属性都存储在 __dict__ 字典中。...,Python 会:在类级别创建一个固定的内存布局,类似 C 语言中的结构体不再为实例创建 __dict__ 和 __weakref__ 属性(除非显式添加到 __slots__ 中)将属性直接存储在预分配的固定大小的数组中...装饰器默认不会使用 __slots__,每个实例依然会创建 __dict__Python 3.10的改进:引入了 slots=True 参数,可以自动为 dataclass 启用 __slots__动态添加属性的陷阱..._ 是个好选择如果类的属性集合是确定的,使用 __slots__ 可以获得更好的代码质量记住:过早优化是万恶之源,先保证代码正确性和可维护性总结__slots__ 不仅仅是一个性能优化工具,它还能帮助我们写出更清晰
目录 一、内置属性__slots__。 1.如果没有这句__slots__ = ['name']代码,正常情况下是可以添加属性的。 2.写了属性限制。 3.现在只能添加name这一个属性。...一、内置属性__slots__ 自己定义一个类,事先定义一个__slots__属性,创建一个对象的时候,这个对象就不会自动生成__dict__属性了。这个是关于节约内存方面的东西。...1.如果没有__slots__ = ['name']这句代码,正常情况下是可以添加属性的: # __slots_ #限制对象的属性。...限定之后,只能为这个对象绑定这个属性,其它的属性再也绑定不上去了。 2.节约内存 通过这个类创建了一个对象,这个时候Python会自动生成一个__dict__。...定义slots之后,就不会自动创建__dict__了。 所以创建一个类的时候,知道这个类有多少个属性。
Cloneable接口与Serializable接口都是定义接口而没有任何的方法。Cloneable可以实现对象的克隆复制,Serializable主要是对象序列化的接口定义。...很多时候我们涉及到对象的复制,我们不可能都去使用setter去实现,这样编写代码的效率太低。JDK提供的Cloneable接口正是为了解决对象复制的问题而存在。...Cloneable结合Serializable接口可以实现JVM对象的深度复制。...重写(override)Object类的clone()方法。 普通对象的克隆是克隆属性的值,而不是引用。...1L,一个是随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具生成) // 如果没有特殊需求,就是用默认的 1L 就可以 static final long serialVersionUID
当一个类需要创建大量实例时,可以通过__slots__声明实例所需要的属性,本文介绍__slots__相关内容。...限制变量范围 为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性: class Student: __slots...python的动态性一部分源自于__dict__,属性都保存在__dict__的一个字典中,我们可以随时向这个字典添加新内容,这是MonkeyPatch的能力。...而当我们显示的声明了__slots__,python将不会给这个类创建__dict__ 和 __weakref__ 注: __weakref__是软引用,类似于指针,不会增加引用计数器 继承问题...准确的说,__slots__不会被继承。当我们用一个不带有__slots__的子类,继承带有__slots__的父类时。子类还是会生成__dict__ 和 __weakref__。
vars()函数是一个内置函数,用于返回对象的__字典__,其中包含对象的__属性__。它适用于模块、类和实例对象,为你提供了访问对象属性的便捷方式。...使用 vars() 函数的示例示例 1: 在模块中使用 vars()python复制代码# 创建一个模块# file: my_module.pyvar_in_module = "I'm in the module...vars() 函数是Python中强大而多用途的函数之一。它可以帮助你动态地查看和操作对象的属性。通过了解它的用法,你可以更好地利用它来简化代码和探索对象的结构。4. 更深入的应用和用例a....__ 的关系在某些情况下,对象使用__slots__属性而不是__dict__来存储实例变量。...它适用于模块、类和实例对象,让你更好地理解对象的内部结构。通过了解和熟练使用vars()函数,可以更高效地编写代码,进行调试和探索Python对象。
判断一个对象是否属于一个类,使用内建函数isinstance(),用它可以判断一个对象是否是一个类或者子类的实例;也可以判断一个对象是否是某个类型。...它不像__dict__属性是类和每个对象都是自己独立的,可以存放各自的属性。 __slots__总结: 1....如果有一个属性很少的类,但是有很多实例,每个实例又不需要定义各自的实例属性,此时为了节省内存,可以使用__slots__取代__dict__。 ...,对象也只能使用那些属性,对象不能自己去创建新属性(因为没有了__dict__),也不能修改类的属性,因为受类控制。 ...关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。
现在第二个object也没有指向它的东西,所以也将被垃圾收集丢掉。 为了能够验证所有这些,我们可以使用内置函数id。id 获得对象在内存中的确切位置,表示为数字。...如果你想要一个明确的答案,知道一个对象上可以访问哪些属性,你可以使用dir >>> dir(c) ['__class__', '__delattr__', '__dict__', '__dir__',...由于某种奇怪的原因,无法将任意变量赋给object,但是可以赋给自己创建的类的对象。 这是object的特性吗?...这两种不同的存储数据方式,在Python中用__dict__和__slots__呈现。通常,实例属性(如self.foo)存储在__dict__字典中。...让我们尝试用以下函数之一构建一些有意义的东西: 有时您需要创建一个必须重载的函数,以便直接获取值或获取“工厂”对象,例如,它可以是对象或函数,它可以按需生成所需的值。
__call__ 正常情况下定义了一个类,调用这个类表示创建一个对象。 class cls: pass c = cls() 但是,对象c不再是可调用的对象,也就是说,它不能再被执行。...__定义在类级别上,它仅仅只限定实例对象属性,不会限制类属性 __slots__不会被子类继承 __slots__定义后,对象默认就没有了__dict__属性 但可以将__dict__放进...__dict__.keys()) # 报错,对象没有__dict__属性 可以将__dict__放进__slots__中,使得对象可以带有属性字典。...但这会让__slots__的限定失效:实例对象可以继续添加任意属性,那些不在__slots__中的属性会加入到__dict__中。..._slots__的话,因为子类可以访问父类的__dict__,这会使得子类自身定义的__slots__的属性限定功能失效。
比如我们来看一个很简单的例子,由于Python是动态语言,所以类的成员甚至可以在类创建好了之后动态创建。这在静态语言当中是绝对不行的,我们只能调用类当中已有的属性,是不能或者很难添加新属性的。...,提示你Exp这个对象当中并没有c这个成员,也就是说我们只能运用__slots__这个关键字当中定义的成员,对于没有定义的成员不能随意创建,这样就限制了用户的使用。...如果了解过Python底层的实现原理,你会发现在Python当中为每一个实例都创建了一个字典,就是大名鼎鼎的__dict__字典。...这个对象当中没有__dict__这个成员。...原因很简单,因为使用dict来维护实例,会消耗大量的内存,额外存储了许多数据,而使用__slots__之后,Python内部将不再为实例创建一个字典来维护,而是会使用一个固定大小的数组,这样就节省了大量的空间
下边有一个函数可以通过递归的方式,调用getsizeof函数,计算对象实际数据量。...get_size ([d1, d2, d1])的结果更有趣——我们得到了871字节,只是稍微多一点,也就是说Python足够聪明,不会再次为同一个对象分配内存。 现在,我们来看一看问题的第二部分。...Python是一个解释器,我们可以在任何时候扩展我们的类,例如,添加一个新的字段: d1 = DataItem("Alex", 42, "-") print ("get_size(d1):", get_size...另外,创建对象的速度要快20%(请参阅本文的第一个屏幕截图)。 唉,真正使用如此大的内存增益并不是因为其他开销。...激活__slots__禁止所有元素的创建,包括__dict__,这意味着,例如,一下代码将结构转换成json将不运行: def toJSON(self): return json.dumps(self
在本文中,我们将讨论缩小对象的方法,大幅减少 Python 所需的内存。 为了简便起见,我们以一个表示点的 Python 结构为例,它包括 x、y、z 坐标值,坐标值可以通过名称访问。...带有 __slots__ 的类实例 为了大幅降低内存中类实例的大小,我们可以考虑干掉 __dict__ 和__weakref__。...namedlist.namedlist 函数可以创建带有 __slots__ 的类: >>> Point = namedlist('Point', ('x', 'y', 'z')) 还有一个包 attrs...该方案的优点是字段可以使用 C 语言的原子类型。访问字段的描述符可以通过纯 Python 创建。...总结 在本文中,我们通过一个简单明了的例子,求证了 Python 语言(CPython)社区的开发人员和用户可以真正减少对象占用的内存量。
在本文中,我们将讨论缩小对象的方法,大幅减少 Python 所需的内存。 ? 为了简便起见,我们以一个表示点的 Python 结构为例,它包括 x、y、z 坐标值,坐标值可以通过名称访问。...02.带有 __slots__ 的类实例 为了大幅降低内存中类实例的大小,我们可以考虑干掉 __dict__ 和__weakref__。...namedlist.namedlist 函数可以创建带有 __slots__ 的类: >>> Point = namedlist('Point', ('x', 'y', 'z')) 还有一个包 attrs...该方案的优点是字段可以使用 C 语言的原子类型。访问字段的描述符可以通过纯 Python 创建。...09.总结 在本文中,我们通过一个简单明了的例子,求证了 Python 语言(CPython)社区的开发人员和用户可以真正减少对象占用的内存量。
1 对象的格式化输出 (1)如果需要对一个对象(实例)进行格式化输出,可以重写类的__repr__()和__str__()方法。...__doc__) # description... 3 获取类或对象的所有成员 可以通过__dict__获取到类或对象的所有成员信息(字典形式),用法 【类名.__dict__】或者【对象....(2)使用__slots__后的类所创建的对象只会用到这些_slots__定义的字段,也就是说,每个对象都是通过一个很小的固定大小的数组来构建字段,而不是字典。...需要注意的是: (1)如果声明了__slots__,那么对象就不会再有__dict__属性。...(3)这里多说一句,于我们而言,Person是我们定义的一个类;于MyType而言,Person是MyType创建的一个对象。
下边有一个函数可以通过递归的方式,调用getsizeof函数,计算对象实际数据量。...Python是一个解释器,我们可以在任何时候扩展我们的类,例如,添加一个新的字段: d1 = DataItem("Alex", 42, "-") print ("get_size(d1):", get_size...另外,创建对象的速度要快20%(请参阅本文的第一个屏幕截图)。 唉,真正使用如此大的内存增益并不是因为其他开销。...激活__slots__禁止所有元素的创建,包括__dict__,这意味着,例如,一下代码将结构转换成json将不运行: def toJSON(self): return json.dumps...奇怪的是在Habré从来没有详细分析使用__slots__,我希望本文将填补这一空缺。 结论 这篇文章似乎是一个anti-Python广告,但并不是。
在GitHub上,有一个函数可以计算实际大小,通过递归调用所有对象的getsizeof实现。...get_size([d1,d2,d1])的结果更加有趣,它产生了871个字节,只是稍微多了一点,这说明Python很聪明,不会再为同一个对象分配内存。 现在我们来看问题的第二部分。...Python是一个解释器,我们可以随时扩展我们的类,例如,添加一个新字段: d1 = DataItem("Alex", 42, "-") print ("get_size(d1):", get_size...作为奖励,对象的创建速度提高了约20%(请参阅文章的第一个屏幕截图)。 真正使用如此大的内存增益不会导致其他开销成本。...激活__slots__会禁止创建其他所有元素,包括__dict__,这意味着,例如,下面这种将结构转换为json的代码将不起作用: def toJSON(self): return json.dumps
---- __slots__允许我们声明并限定类成员,并拒绝类创建__dict__和__weakref__属性以节约内存空间。...Python是动态语言,对于普通的类,可以为类实例赋值任何属性,这些属性会存储在__dict__中: class Persion(object): pass p=Persion() p.name...通过__slots__属性限定类属性的创建: class Persion(object): __slots__ = ['name','age'] pass p=Persion() p.name...,在定义了__slots__变量后,Student类实例已经不能随意创建不在__slots__定义内的属性phone,同时实例中也不再有__dict__结构。...使用: __slots__在继承中有两种表现: 子类未声明__slots__时,不继承父类的__slots__,即此时子类实例可以随意赋值属性 子类声明__slots__时,继承父类的__slots_
下边有一个函数可以通过递归的方式,调用getsizeof函数,计算对象实际数据量。...get_size ([d1, d2, d1])的结果更有趣——我们得到了871字节,只是稍微多一点,也就是说Python足够聪明,不会再次为同一个对象分配内存。...另外,创建对象的速度要快20%(请参阅本文的第一个屏幕截图)。 唉,真正使用如此大的内存增益并不是因为其他开销。...激活__slots__禁止所有元素的创建,包括__dict__,这意味着,例如,一下代码将结构转换成json将不运行: def toJSON(self): return json.dumps...奇怪的是在Habré从来没有详细分析使用__slots__,我希望本文将填补这一空缺。 结论 这篇文章似乎是一个anti-Python广告,但并不是。
Python一切皆对象,对象都有很多属性和方法,使用时我们怎么知道对象有哪些属性,以及如何获取对象的属性和设置对象的属性呢?...Python提供了dir,hasattr,getattr,setattr,vars等函数,可以帮助我们操作和使用对象的属性。...getattr获取对象的方法时,会返回一个方法对象,我们可以像执行函数一样执行这个方法。 ?...把object对象指定属性的值设为value,前提是object对象能接受那个值。这个函数可能会创建一个新属性,或者覆盖现有的属性。...五、vars([object]) 返回object 对象的 __dict__ 属性,如果实例所属的类定义了__slots__ 属性,实例没有__dict__属性,那么 vars 函数不能处理这个实例(相反
符合 Python 风格的对象 在 Python 中,自定义的类也可以表现得像内置类型一样自然,这都得益于鸭子类型:我们只需按照预定行为实现对象所需的方法即可。...这篇文章主要介绍自定义类的一些特殊方法,来让类的行为跟真正的 Python 对象一样。 类的特殊方法 类的特殊方法是为了被解释器调用,目的是可以将一些内置的方法用在对象上。...类的属性 在 Python 的底层实现中,类的所有对象的属性都存在 __dict__ 属性中,且所有对象的属性共用 key 。...Python 不能像其他语言一样用 private 修饰符来创建私有属性,但是有一个简单的机制来避免子类意外覆盖私有属性,即以 __ 开头来标记属性私有化,比如上面例子中 __integer 和 __decimals...有几点需要注意的是: 每个子类都要定义 __slots__ 属性,因为解释器会忽略继承该属性; 对象只能拥有 __slots__ 中列出的属性,除非将 __dict__ 加入其中; 用户自定义的类中默认有
领取专属 10元无门槛券
手把手带您无忧上云