前言
本博客主要为了解决Python学习中的易混淆和模糊点。如果你系统学过Java,对于Java的内存原理那一套有一点简单的基础,本节就将没有任何难度,并且会将你的Python水平上升一个档次。
先指出Python中的几个重要事实:
- Python中万物都是对象,整数是对象,列表是对象,我们的自定义类也是对象。
- Python中变量赋值(一个变量赋值给另一个变量)、函数传参,总之Python中传参都传的是引用(地址)。
一 Python中的一些内存原理
Java数组的内存原理
先看一下这篇文章,了解一下什么叫栈空间,堆空间。并且理解一下Java中的数组内存原理,就可以直接迁移到我们这里的列表内存原理上。
1 整数(int)的内存原理
a = 10
这个代码在内存里面发生了什么,我们画个内存图就理解了。由于直接运行这个,Python底层会自动放进一个方法里面的,我们就不妨假设是main方法吧!(Java里面就是叫main方法)。很显然main方法进栈空间,下面开辟了一个a变量空间,看下面内存图。
进一步
a = 10
b = a # 把a的引用(地址)传给了b. 此时 a和b指向内存同一个int对象
2 列表的内存原理
同样,我们要理解下面代码过程发生了什么?
lst = [1, 2, 3]
3 小总结
其实Python中万物都是对象,记住这个就可以了。其他数据类型或者自定义类都可以按照上面这一套来,学会画内存图就懂了。
还有一个可变数据和不可变数据的修改,需要在可变数据和不可变数据哪里具体说明。
二、可变数据与不可变数据
1 概念
数据类型 | 描述 |
---|---|
可变数据 (列表、字典、集合) | 可变数据类型(Mutable Data Types)指的是可以在原地直接修改其内容的对象类型。这意味着,当你对该对象进行操作时,不会创建新的对象,而是在内存中对原对象进行修改。 |
不可变数据(整数、浮点数、布尔类型、字符串、元组) | 不可变数据类型(Immutable Data Types)是指一旦创建,它们的内容就无法修改。对不可变对象的操作通常会生成一个新的对象,而不是修改原对象。 |
Java中的可变与不可变(与python中是同一个意思):
(1)Java中的int、double这类基本数据类型(非对象,直接存在栈空间中)直观上是可变的
(2)int、double的包装类是不可变的(因此Java集合api里面使用的都是基本数据类型的包装类,而不是基本数据类型),这样就完全和Python里面对应起来了
2 自定义一个不可变类(就像python和Java中的字符串都是不可变的,修改本质上是创建了一个新的字符串对象绑定到变量上)
在 Python 中,创建一个不可变类通常是为了保证类的实例一旦创建,其属性就不能被修改。这类似于 Python 中的不可变数据类型(如 tuple 和 str),即实例的状态是不可更改的。
创建一个不可变类,其实很简单,将里面属性私有化、并且不提供修改方法。
- 使用
__slots__
属性来限制对象的属性。 - 确保在类中不提供修改对象状态的方法(不要提供set方法 , get方法必须使用@property 装饰器,不要提供set方法 。 )。
- 在类中使用只读属性,即属性的值在初始化后不能修改。
以下是一个简单的示例,演示了如何创建一个不可变类:
class ImmutableClass:
def __init__(self, value):
self._value = value # 使用下划线表示属性是私有的,并且在初始化后不会修改
@property
def value(self):
return self._value # 提供只读属性
解释: 可以通过使用 @property 装饰器,将类的属性定义为只读,这样外部代码无法直接修改它们。
三 python中的变量赋值操作理解(很重要)== 画大量内存图来理解
在Python中,赋值操作有多种形式,而它们在不同的上下文中可能有不同的效果。为了更好地理解Python的赋值机制,我们需要明确以下几个概念:
- 对象和引用:Python中的一切都是对象,变量只是这些对象的引用。
- 赋值操作的不同效果:赋值操作不仅仅是创建新对象,更多的是将引用绑定到对象上。
- 可变性和不可变性:对象的可变性决定了赋值和操作对对象本身和引用的影响。
1 Python的变量赋值内存案例
---- 示例1
a = 10
b = a # 把a的引用(地址)传给了b. 此时 a和b指向内存同一个int对象
---- 示例2:整数是不可变的
b = 10
b +=