许多编程初学者习惯将变量视为存储数据的“容器”或“盒子”,但在Python中,这种理解其实是不准确的,甚至会导致一系列困惑。本文将深入剖析Python变量的本质,帮助初学者建立正确的思维模型。
一、变量的本质:指向内存中对象的标签或引用
Python世界中,万物皆可被当做对象,当对象创建后,每个对象都会有唯一确定的内存位置,就像身份证号一样。我们可以直接使用对象本身进行运算、传参等操作,但更多时候,使用变量会使代码更易读。变量并不是存储数据的容器,而是指向内存中对象的标签或引用。这是理解Python变量最重要的核心观点。每个对象都有唯一确定的内存位置,想确定不同变量是否引用或指向了同一个对象,可以比较他们的内存位置是否相同。比如下面代码示例:Python示例代码:
执行结果:
第一行代码:python创建了“我是一个字符串”的对象,然后被变量S引用;第二行代码:python创建了“我也是一个字符串”的对象,被变量T引用;第四、五、六行代码:分别打印变量S/T/U的内存地址。注意:每次执行代码时,python会创建新的列表对象,所以每次运行的内存地址可能不同。从执行结果看,变量S跟变量U的内存地址是相同的,所以可以说变量S跟变量U引用的是同一个对象。变量T跟S和U的内存地址不同,因此引用的是不同的对象。我们在使用对象时,可以给它贴上任意标签,一个对象是可以有多个标签的,比如:Python示例代码:
执行结果:
上面示例代码中,首先python在内存中创建了一个列表对象[1,2,3,4,5],然后将变量A、B、C都指向了该列表对象;也可以说,列表[1,2,3,4,5]被贴上了标签A、B、C。但无论有多少个标签,对象确定后,它在内存中的位置是不变的。【思考】:上面代码中,ABC都指向了同一个对象,他们的值是一样的,我们是否可以说,只要变量的值相同,就说明变量都引用或指向了同一个对象?这个观点是错误的。我们要从变量的本质去思考这个问题:变量是内存中对象的标签或引用,每个对象都有唯一内存地址,变量指向的内存地址相同,才能说明是变量引用或指向了同一个对象。请看代码示例:
代码示例:
执行结果:
第一行代码:创建了一个[1,2,3,4,5]的列表对象,被变量M引用。第二行代码:又创建了一个[1,2,3,4,5]的列表对象,被变量N引用。第四行代码:比较M和N是不是同一个对象,并打印结果。从上述代码执行结果看,变量M和N的值是相同的,但是他们却是不同的对象,因为他们指向的内存地址不一样。所以,我们可以得出问题答案:变量的值相同,并不能说明这两个变量引用或指向了同一个对象。就像双胞胎一样,模样相同,但本质上是两个不同的个体(对象)。二、可变对象与不可变对象
从字面上看似很好理解,但到底是什么意思呢?这还是要结合“变量的本质”去理解。(一)可变对象
对于可变对象,修改变量指向的内容时,不会创建新对象,还是在原来的对象上操作。常见可变对象比如:list, dict, set。如代码示例:代码示例:
执行结果:
代码分析:先是创建了一个列表对象,被变量P引用,又用变量Q指向了P的引用,可以说P和Q指向的是同一个内存地址。然后用append方法修改了变量P引用的列表对象,我们发现,P和Q的值都发生了变化,但是修改前后对象的内存地址并未发生改变。这就是可变对象,修改对象后,本身发生了变化,但是内存地址不变。(二)不可变对象
对于不可变对象,本质上无法修改对象本身,你以为的“修改,其实是创建了一个新对象,然后把变量指向了这个新对象,而原来的对象还在那里。常见的不可变对象比如:int, float, str, tuple等。如代码示例:代码示例:
执行结果:
如代码示例,先是创建了一个数值对象,被变量X引用,又用变量Y引用了X的指向,可以说此时X和Y指向的是同一个内存地址。然后对变量X的值进行了修改又重新指向了X。执行结果后我们发现,只有X的值和内存地址都发生了变化,但是Y的值和内存地址并未发生改变。这就是不可变对象。对象本身无法被修改,我们以为的修改,本质上是创建了一个新对象。三、总结回顾
- 变量的本质:指向内存中对象的标签或引用。变量不是容器。
- python对象:每个对象都有唯一确定的内存地址。(可使用方法id()查看)。
- 区分可变与不可变对象:理解哪些对象可以原地修改,哪些会创建新对象。
- 多个变量指向同一可变对象时,当某个变量发生变化,有可能导致对象本身被意外修改。
记住:在Python中,对象是实体,变量是标签或引用。掌握这个简单的概念,是深入理解Python的关键一步,能助你更好地驾驭Python的强大功能,写出更优雅、高效、健壮的代码。