在Python中,变量是存储数据的容器,用来存储程序运行过程中需要使用的数据。
数据类型决定了变量可以存储的数据种类。Python的变量无需声明类型,赋值后即可创建,且支持动态类型。
命名规则和规范
| 规则 |
|---|
| 只能包含大小写字母、数字、下划线 |
| 不能以数字开头 |
| 严格区分大小写 |
| 不能使用Python内置关键字和预留关键字 |
| 规范 | 示例 |
|---|---|
| 推荐变量名使用小写字母 + 下划线(蛇形命名法) | user_name、max_score |
| 常量使用全大写 + 下划线 | MAX_SIZE、PI |
| 见名知意,避免无意义的单字母 | 用 student_count 而不是 n |
变量的本质
Python 中变量存储的其实是对象的引用(可以理解为指向数据的”标签”),也可以说变量是对内存及其地址的抽象。
变量的存储,采用了引用语义的方式,存储的只是一个变量的值所在的内存地址,而不是这个变量本身。
变量所需的存储空间大小一致,因为变量只是保存了一个引用。也被称为对象语义和指针语义。变量的每一次初始化,都开辟了一个新的空间,将新内容的地址赋值给变量
用 id() 函数可以查看变量指向的内存地址:
1 | a = 100 |
这里 b = a 并不是把 a 的值复制一份给 b,而是让 b 也指向 a 所指向的那个 100。所以即使a重新赋值后,也不会影响b,因为b本身存储的是内存堆中的地址,而a则重新保存了新的内存地址。
如果不使用 b = a,而是各自赋一个值:
1 | a = 100 |
a 和 b 各自独立赋值为 100,id() 居然一样——它们指向了同一个对象。但如果换成一个大数:
1 | a = 1000 |
这就是 Python 的小整数池(small integer caching):Python 启动时会预创建 -5 到 256 之间的所有整数对象。程序中任何用到这个范围内的整数时,都会直接复用池中已有的对象,而不会创建新对象。
-5~256:复用同一个对象超出这个范围:每次创建新对象
为什么是 -5 到 256?这是 Python 开发者基于大量实际代码统计出来的——程序中出现的整数绝大多数落在这个区间。预创建它们可以避免频繁创建和销毁小整数,提升性能、节省内存。
因为这个机制,对小整数用
is比较的结果可能”碰巧正确”,但不要依赖它。判断数值相等请始终用==。is只用于判断是否为同一个对象(比如和None比较)。
变量作用域
作用域(Scope)是指程序中变量、函数或其他标识符的可见性和可访问性范围。它决定了在代码的哪些部分可以引用或修改某个变量。
Python 中的作用域主要分为以下四种类型:
局部作用域(Local Scope)
- 定义在函数内部的变量属于局部作用域
- 只能在函数内部访问
- 函数执行结束后,局部变量会被销毁
嵌套作用域(Enclosing Scope)
- 在嵌套函数中,外层函数的作用域
- 内层函数可以访问外层函数的变量
- 但不包括全局变量和内置变量
全局作用域(Global Scope)
- 定义在函数外部的变量属于全局作用域
- 可以在整个程序中被访问
- 需要使用 global 关键字在函数内部修改全局变量
内置作用域(Built-in Scope)
- Python 内置的函数和变量(如 print()、len() 等)
- 在任何地方都可以访问
1 | x = 10 # 全局作用域 |
Python 会按照 LEGB 规则(Local -> Enclosing -> Global -> Built-in)查找变量,但不会自动在局部作用域中修改全局变量。
在函数内部修改全局变量需要使用
global关键字声明
嵌套作用域中修改外层变量需要使用nonlocal关键字
变量生命周期
在Python中,变量的创建和销毁是由解释器自动管理的。创建时机是指变量首次被赋值时,解释器为其分配内存空间;销毁时机是指变量不再被引用时,解释器回收其占用的内存。
常见误区或注意事项
- 误认为
del会立即释放内存:del只是删除引用,实际内存回收由垃圾回收器(GC)决定。 - 循环引用导致内存泄漏:相互引用的对象可能无法被自动回收,需手动解除引用。
- 全局变量不会自动销毁:除非程序结束或显式删除,否则一直存在。
1 | # 变量创建 |