====== 第二章:变量与数据类型 ======
===== 本章目标 =====
完成本章学习后,你将能够:
* 理解变量的本质和Python的变量模型
* 掌握Python的所有基本数据类型
* 理解可变对象与不可变对象的区别
* 掌握类型转换和类型检查
* 理解Python的内存管理机制
===== 变量基础 =====
==== 什么是变量 ====
在编程中,**变量**是用于存储数据的命名位置。可以将变量看作是一个贴有标签的盒子,盒子里装着数据。
# 变量赋值
name = "Alice"
age = 25
pi = 3.14159
==== Python的变量模型 ====
Python的变量与其他语言不同。在Python中:
* **变量是指向对象的引用**,而不是存储数据的盒子
* **赋值操作是将名字绑定到对象**,而不是复制数据
# 图解:变量与对象
a = [1, 2, 3] # a指向列表对象
b = a # b也指向同一个列表对象
b.append(4) # 修改列表
print(a) # [1, 2, 3, 4] —— a也变了!
内存示意:
变量a ──→ [1, 2, 3, 4] ←── 变量b
==== 变量命名规则 ====
1. 只能包含字母、数字、下划线
2. 不能以数字开头
3. 不能是Python关键字
4. 区分大小写
# 合法变量名
name = "Alice"
_name = "private"
name2 = "Bob"
user_name = "Charlie"
UserName = "David" # 不同变量
# 非法变量名
2name = "error" # SyntaxError:不能以数字开头
my-name = "error" # SyntaxError:不能包含连字符
my name = "error" # SyntaxError:不能包含空格
class = "error" # SyntaxError:关键字
==== Python关键字 ====
以下单词是Python保留的,不能用作变量名:
import keyword
print(keyword.kwlist)
# ['False', 'None', 'True', 'and', 'as', 'assert', 'async',
# 'await', 'break', 'class', 'continue', 'def', 'del',
# 'elif', 'else', 'except', 'finally', 'for', 'from',
# 'global', 'if', 'import', 'in', 'is', 'lambda',
# 'nonlocal', 'not', 'or', 'pass', 'raise', 'return',
# 'try', 'while', 'with', 'yield']
===== 基本数据类型 =====
Python有以下基本数据类型:
| 类型 | 名称 | 示例 | 说明 |
| int | 整数 | 42, -100, 0 | 任意精度整数 |
| float | 浮点数 | 3.14, -0.5 | 双精度浮点数 |
| bool | 布尔值 | True, False | 逻辑值 |
| str | 字符串 | "hello" | 文本数据 |
| NoneType | 空值 | None | 表示无值 |
==== 整数(int)====
Python的整数可以**任意精度**,只受限于可用内存。
# 整数定义
a = 42
b = -100
c = 0
# 不同进制
binary = 0b1010 # 二进制,等于10
octal = 0o777 # 八进制,等于511
hexadecimal = 0xFF # 十六进制,等于255
# 大整数(Python自动处理)
big_number = 123456789012345678901234567890
print(big_number * big_number) # 不会溢出!
# 类型检查
print(type(a)) #
==== 浮点数(float)====
Python的float是**双精度浮点数**(IEEE 754标准,64位)。
# 浮点数定义
pi = 3.14159
negative = -0.5
scientific = 1.5e-3 # 科学计数法,等于0.0015
# 浮点数精度问题
print(0.1 + 0.2) # 0.30000000000000004,不是精确的0.3!
# 解决方案:使用decimal模块
from decimal import Decimal
a = Decimal('0.1')
b = Decimal('0.2')
print(a + b) # 0.3,精确计算
# 无穷大和NaN
inf = float('inf')
neg_inf = float('-inf')
not_a_number = float('nan')
==== 布尔值(bool)====
布尔类型只有两个值:**True** 和 **False**。
# 布尔值
flag = True
empty = False
# 布尔运算
print(True and False) # False
print(True or False) # True
print(not True) # False
# 比较运算产生布尔值
print(5 > 3) # True
print(5 == 3) # False
# 类型实际上是int的子类
print(isinstance(True, int)) # True
print(True + True) # 2(True等于1)
print(False * 10) # 0(False等于0)
==== 空值(None)====
**None** 表示 absence of a value(无值)。
# None表示没有值
result = None
# 函数默认返回值
def do_nothing():
pass
print(do_nothing()) # None
# 检查是否为None
if result is None:
print("还没有结果")
# 注意:不要用 == 检查None,要用 is
print(result == None) # True,但不推荐
print(result is None) # True,推荐方式
===== 类型检查与转换 =====
==== type()函数 ====
# 检查变量类型
print(type(42)) #
print(type(3.14)) #
print(type("hello")) #
print(type(True)) #
print(type(None)) #
==== isinstance()函数 ====
# 检查是否为特定类型
print(isinstance(42, int)) # True
print(isinstance(3.14, (int, float))) # True,检查多个类型
# isinstance vs type
class Animal:
pass
class Dog(Animal):
pass
dog = Dog()
print(type(dog) == Animal) # False
print(isinstance(dog, Animal)) # True,考虑继承
==== 类型转换 ====
# 转换为整数
print(int(3.14)) # 3,截断小数部分
print(int("42")) # 42
print(int("1010", 2)) # 10,二进制转十进制
print(int(3.9)) # 3,不是四舍五入!
# 转换为浮点数
print(float(42)) # 42.0
print(float("3.14")) # 3.14
# 转换为字符串
print(str(42)) # "42"
print(str(3.14)) # "3.14"
print(str(True)) # "True"
print(str([1, 2, 3])) # "[1, 2, 3]"
# 转换为布尔值
print(bool(1)) # True
print(bool(0)) # False
print(bool("hello")) # True,非空字符串
print(bool("")) # False,空字符串
print(bool([1, 2])) # True,非空列表
print(bool([])) # False,空列表
===== 可变对象与不可变对象 =====
这是Python中**最重要的概念之一**。
==== 不可变对象(Immutable)====
创建后不能被修改的对象:
* int(整数)
* float(浮点数)
* bool(布尔值)
* str(字符串)
* tuple(元组)
* frozenset(冻结集合)
# 整数不可变
a = 5
print(id(a)) # 140735890123456
a = a + 1 # 创建新对象
print(id(a)) # 140735890123488,不同的地址!
# 字符串不可变
s = "hello"
# s[0] = "H" # TypeError: 'str' object does not support item assignment
s = "H" + s[1:] # 创建新字符串
print(s) # "Hello"
==== 可变对象(Mutable)====
创建后可以修改的对象:
* list(列表)
* dict(字典)
* set(集合)
* 自定义类的实例(默认)
# 列表可变
lst = [1, 2, 3]
print(id(lst)) # 4334567890
lst.append(4) # 修改原对象
print(id(lst)) # 4334567890,相同地址!
print(lst) # [1, 2, 3, 4]
lst[0] = 100 # 修改元素
print(lst) # [100, 2, 3, 4]
==== 深浅拷贝 ====
由于可变对象的特性,有时需要创建副本:
import copy
# 浅拷贝
original = [1, [2, 3], 4]
shallow = original.copy() # 或 list(original) 或 original[:]
original[0] = 100
print(shallow[0]) # 1,不变
original[1][0] = 200
print(shallow[1]) # [200, 3],变了!因为内部列表是共享的
# 深拷贝
deep = copy.deepcopy(original)
original[1][1] = 300
print(deep[1]) # [200, 3],不变
===== Python内存管理 =====
==== 引用计数 ====
Python使用**引用计数**来管理内存:
import sys
a = [1, 2, 3]
print(sys.getrefcount(a)) # 2(a的引用 + getrefcount的参数引用)
b = a
print(sys.getrefcount(a)) # 3
del b
print(sys.getrefcount(a)) # 2
当对象的引用计数降为0时,内存会被回收。
==== 垃圾回收 ====
对于循环引用,Python使用**垃圾回收器(GC)**:
import gc
# 手动运行垃圾回收
gc.collect()
# 查看垃圾回收统计
print(gc.get_stats())
# 禁用/启用垃圾回收
gc.disable()
# ... 做一些性能敏感的操作 ...
gc.enable()
==== 小整数缓存 ====
Python缓存了小整数(-5到256):
a = 100
b = 100
print(a is b) # True,同一个对象
c = 1000
d = 1000
print(c is d) # False(在某些Python实现中可能是True)
==== 字符串驻留 ====
Python会**驻留**(intern)一些字符串:
a = "hello"
b = "hello"
print(a is b) # True
c = "hello world!"
d = "hello world!"
print(c is d) # False,长字符串不一定驻留
# 手动驻留
e = sys.intern("hello world!")
f = sys.intern("hello world!")
print(e is f) # True
===== 变量作用域 =====
==== LEGB规则 ====
Python按以下顺序查找变量:
* **L**ocal —— 局部作用域
* **E**nclosing —— 嵌套函数的外层函数作用域
* **G**lobal —— 全局作用域
* **B**uilt-in —— 内置作用域
# 示例
x = "global" # G
def outer():
x = "enclosing" # E
def inner():
x = "local" # L
print(x) # 输出 "local"
inner()
print(x) # 输出 "enclosing"
outer()
print(x) # 输出 "global"
==== global和nonlocal ====
count = 0
def increment():
global count # 声明使用全局变量
count += 1
increment()
print(count) # 1
def outer():
value = 10
def inner():
nonlocal value # 使用外层函数的变量
value = 20
inner()
print(value) # 20
outer()
===== 本章练习 =====
1. **类型检测器**:编写程序接收用户输入,判断并输出其数据类型
2. **温度转换器**:编写程序在摄氏、华氏、开尔文温度之间转换
3. **内存探秘**:使用id()函数验证可变与不可变对象的行为差异
4. **深浅拷贝实验**:创建一个包含多层嵌套的列表,验证深浅拷贝的区别
5. **变量交换**:不使用临时变量,交换两个变量的值
===== 本章小结 =====
本章我们深入学习了:
* Python的变量模型(引用语义)
* 基本数据类型及其特性
* 类型检查与转换
* 可变对象与不可变对象的区别(关键概念!)
* Python内存管理机制
* 变量作用域规则
理解可变与不可变对象是掌握Python的关键,这将帮助你避免许多常见的编程错误。
下一章:[[python_course:chapter03|第三章:运算符与表达式]]