什么是变量?(便利贴 vs 盒子)

在传统的静态语言(如 C 语言)中,变量通常被比喻为一个盒子:你申请一个盒子,给它贴上名字,然后把数据放进去。

但在 Python 中,变量更像是一个便利贴(标签)

  • 对象(Object):是内存中实实在在存储数据的地方(比如数字 10,字符串 "Hello")。
  • 变量(Variable):只是一个名字,你把这个名字“贴”到了某个对象上。

核心概念: 变量本身不存储数据,它只是指向了存储数据的内存地址。

变量的基本用法

Python 是动态类型语言,这意味着你不需要显式声明变量的类型(如 int a),直接赋值即可使用。

基础赋值

# 将 "score" 这个标签贴在数字 100 上
score = 100

# 将 "username" 这个标签贴在字符串 "Alice" 上
username = "Alice"

print(score)      # 输出: 100
print(username)   # 输出: Alice

动态类型特性

同一个变量名可以随时被贴到不同类型的对象上:

var = 123       # var 现在指向整数
print(var)

var = "Python"  # var 现在指向字符串(类型变了,但在Python中是合法的)
print(var)

深入理解:内存引用与 id() 函数

这是理解 Python 变量逻辑最关键的一步。为了验证“变量是引用”这一说法,我们需要使用 Python 的内置函数 id()

  • id(object):返回对象的“身份”,在 CPython 实现中,这通常就是对象在内存中的地址
  • Python 是一种编程语言,它是一套语法规范和语义规则,但是它本身不能直接运行代码。为了执行 Python 代码,我们需要一个解释器(Interpreter)。CPython 是最常用的 Python 解释器的实现,它使用 C 语言编写,并且在 CPython 中,id() 函数返回的是对象在内存中的地址。
  • CPython 是 Python 语言的官方参考实现,由 Python 创始人 Guido van Rossum 主导开发,用 C 语言 编写,因此得名 C + Python = CPython。当你从 python.org 下载并安装 Python 时,你安装的就是 CPython。

示例:查看变量的内存地址

x = 10
print(f"x的值: {x}, x的内存地址: {id(x)}")

# 让我们看看发生了什么
y = 10
print(f"y的值: {y}, y的内存地址: {id(y)}")

运行结果(示例):

x的值: 10, x的内存地址: 4304675344
y的值: 10, y的内存地址: 4304675344

分析:
你会发现 xyid 是一样的!

  • Python 内存中创建了一个整数对象 10
  • x = 10:把标签 x 贴在对象 10 上。
  • y = 10:Python 检测到内存中已经有小整数 10 了(由于 Python 的小整数缓存机制),它直接把标签 y 也贴到了同一个对象 10 上。
  • 结论: 变量 xy 指向了同一个内存块。

示例:重新赋值的真相

如果我们修改 x 的值,会发生什么?

x = 10
print(f"初始 x 地址: {id(x)}")

x = 20
print(f"修改后 x 地址: {id(x)}")

分析:
你会发现地址变了

  • 不是把内存中 10 改成了 20
  • 而是在内存中新建(或找到)了一个对象 20,然后把标签 x10 身上撕下来,贴到了 20 身上。
  • 原来的对象 10 如果没有其他变量引用它,稍后会被垃圾回收机制回收。

变量的传递(引用传递)

理解了“便利贴”模型,变量之间的赋值逻辑就很好理解了。

场景一:不可变对象(数字、字符串、元组)

a = 100
b = a  # 把 b 贴到 a 当前指向的对象上

print(f"a的地址: {id(a)}")
print(f"b的地址: {id(b)}") # 地址相同

a = 200 # a 换到了新对象 200 上,b 仍然贴在 100 上
print(f"a的值: {a}, b的值: {b}")

结果: b 依然是 100。因为改变 a 只是移动了 a 这个标签,不影响 b 这个标签。

场景二:可变对象(列表、字典)—— 新手最大的坑

对于列表这种“可变对象”,情况会变得有趣:

list_1 = [1, 2, 3]
list_2 = list_1  # list_2 和 list_1 指向同一个列表对象

print(f"list_1 地址: {id(list_1)}")
print(f"list_2 地址: {id(list_2)}") # 地址完全一样

# 修改 list_1 的内容
list_1.append(4)

print(f"list_1: {list_1}")
print(f"list_2: {list_2}") # 注意:list_2 也变了!

分析:

  • list_1list_2 贴在同一个“箱子”(列表)上。
  • list_1.append(4)往箱子里扔了一个新数据,并没有换箱子(地址没变)。
  • 所以,通过 list_2 往里看,也能看到新增加的数据。

变量表达式赋值

Python 提供了非常优雅的赋值方式,可以让代码更简洁。

1. 链式赋值

将同一个值赋给多个变量:

a = b = c = 0
print(a, b, c)  # 输出: 0 0 0

注意:如果是可变对象(如列表),它们都会指向同一个对象,修改其中一个会影响全部。

2. 解包赋值 (Unpacking)

这是 Python 的杀手级特性,可以同时给多个变量赋值:

# 对应位置赋值
name, age = "Bob", 25
print(name)  # Bob
print(age)   # 25

# 交换变量值(无需中间变量)
x = 5
y = 10
x, y = y, x
print(x, y)  # 输出: 10 5

3. 星号解包

当变量数量和元素数量不匹配时,可以使用 * 收集剩余元素:

data = [1, 2, 3, 4, 5]
head, *middle, tail = data

print(head)   # 1
print(middle) # [2, 3, 4]  <- 变成了一个列表
print(tail)   # 5

变量的命名规范

编写 Python 代码时,遵守 PEP 8(Python 官方编码风格指南)是非常重要的。

命名规则(强制)

  1. 只能包含字母、数字和下划线 (_)。
  2. 不能以数字开头
  3. 区分大小写 (Ageage 是两个变量)。
  4. 不能使用 Python 的关键字(如 if, class, def, return 等)。

命名风格(约定俗成)

  • 普通变量/函数名:使用 Snake Case(蛇形命名法),即全小写,单词间用下划线连接。

    • user_name, total_score, is_active
    • userName (Java风格), UserName, u_n
  • 常量:虽然 Python 没有真正的常量,但约定全大写代表常量。

    • PI, MAX_CONNECTIONS, DEFAULT_COLOR
  • 类名:使用 Camel Case(大驼峰命名法)

    • UserProfile, CarEngine
  • 私有变量(惯例):以单下划线开头,表示不希望被外部访问。

    • _internal_var

代码示例

# 好的命名
student_count = 50
max_score = 100

# 不好的命名
a = 50          # 意义不明
StudentCount = 50 # 像类名,容易混淆
分类: Python 新手教程 标签: 引用内存Python变量

评论

暂无评论数据

暂无评论数据

目录