Python 语法完全指南:从零到进阶

本文系统介绍 Python 语法,从基础到进阶,每个语法点都配有详细示例和练习题,帮助你快速掌握 Python 编程。


目录


一、最基础:运行 & print

1.1 第一个 Python 程序

创建文件:创建一个 .py 文件(如 hello.py

# hello.py
print("Hello, Python")
print("欢迎学习 Python!")

运行方式

# 命令行运行
python hello.py
# 或
python3 hello.py

输出结果

Hello, Python
欢迎学习 Python!

1.2 print 函数详解

基本用法

# 打印字符串
print("Hello")

# 打印多个值(自动用空格分隔)
print("Hello", "World", "Python")

# 自定义分隔符
print("Hello", "World", sep="-")  # 输出: Hello-World

# 自定义结束符(默认是换行)
print("Hello", end="")
print("World")  # 输出: HelloWorld(不换行)

# 格式化输出
name = "Tom"
age = 20
print(f"姓名: {name}, 年龄: {age}")  # f-string(推荐)
print("姓名: {}, 年龄: {}".format(name, age))  # format 方法
print("姓名: %s, 年龄: %d" % (name, age))  # % 格式化(旧式)

1.3 Python 代码规范

缩进规则

  • Python 使用缩进来表示代码块(其他语言用 {}
  • 标准缩进是 4 个空格(不要用 Tab,除非配置了 Tab = 4 空格)
  • 同一代码块必须使用相同的缩进
# 正确示例
if True:
    print("这是 if 代码块")
    print("缩进相同")

# 错误示例(会报错)
if True:
    print("缩进不一致")
  print("这行会报错:IndentationError")

注释

# 单行注释

"""
多行注释
可以用三个双引号
或三个单引号
"""

'''
这也是多行注释
'''

1.4 练习题

练习 1.1:编写程序,打印你的姓名、年龄和爱好(使用 f-string)

查看答案
name = "张三"
age = 25
hobby = "编程"

print(f"姓名: {name}")    # 姓名: 张三
print(f"年龄: {age}")     # 年龄: 25
print(f"爱好: {hobby}")   # 爱好: 编程

练习 1.2:使用 print 打印一个简单的表格(姓名、年龄、城市)

查看答案
print("姓名\t年龄\t城市")
print("-" * 20)
print("张三\t25\t北京")
print("李四\t30\t上海")
print("王五\t28\t广州")

# 输出结果:
# 姓名    年龄    城市
# --------------------
# 张三    25    北京
# 李四    30    上海
# 王五    28    广州

二、变量与基本数据类型

2.1 变量基础

变量命名规则

  • 只能包含字母、数字和下划线
  • 不能以数字开头
  • 区分大小写
  • 不能使用 Python 关键字(如 if, for, def 等)
# 正确命名
name = "Tom"
age = 20
user_name = "admin"
_name = "private"  # 下划线开头(约定为私有变量)

# 错误命名
# 2name = "Tom"  # 不能以数字开头
# user-name = "Tom"  # 不能使用连字符
# if = 10  # 不能使用关键字

变量赋值

# 单个赋值
x = 10
name = "Tom"

# 多重赋值
a, b, c = 1, 2, 3
x = y = z = 0  # 所有变量都赋值为 0

# 交换变量值(Python 特色)
a, b = b, a  # 无需临时变量

动态类型

# Python 是动态类型语言,变量类型可以改变
x = 10        # x 是 int
x = "hello"   # x 现在是 str
x = [1, 2, 3] # x 现在是 list

2.2 数字类型

整数(int)

# 基本整数
a = 10
b = -5
c = 0

# 大整数(Python 3 没有 long 类型,int 可以无限大)
big_num = 123456789012345678901234567890

# 不同进制
binary = 0b1010    # 二进制,值为 10
octal = 0o12       # 八进制,值为 10
hexadecimal = 0xA  # 十六进制,值为 10

# 类型转换
str_num = "123"
int_num = int(str_num)  # 字符串转整数

浮点数(float)

# 基本浮点数
pi = 3.14
negative = -2.5
scientific = 1.23e4  # 科学计数法,值为 12300.0

# 精度问题(注意)
result = 0.1 + 0.2
print(result)  # 0.30000000000000004(浮点数精度问题)

# 类型转换
int_to_float = float(10)  # 10.0
str_to_float = float("3.14")  # 3.14

复数(complex)

# 复数(科学计算用)
c = 3 + 4j
c = complex(3, 4)  # 等价写法

print(c.real)  # 实部:3.0
print(c.imag)  # 虚部:4.0

2.3 字符串类型

字符串创建

# 三种引号都可以
s1 = "双引号"
s2 = '单引号'
s3 = """三引号可以
跨多行"""

# 转义字符
s = "他说:\"你好\""  # 他说:"你好"
s = "第一行\n第二行"  # \n 换行
s = "路径:C:\\Users"  # \\ 表示反斜杠
s = r"C:\Users"  # 原始字符串(raw string),不转义

# f-string(Python 3.6+,推荐)
name = "Tom"
age = 20
s = f"姓名: {name}, 年龄: {age}"  # 姓名: Tom, 年龄: 20

# 表达式
s = f"10 + 20 = {10 + 20}"  # 10 + 20 = 30

字符串常用操作

s = "Python Programming"

# 长度
len(s)  # 18

# 大小写转换
s.lower()      # 'python programming'
s.upper()      # 'PYTHON PROGRAMMING'
s.capitalize() # 'Python programming'
s.title()      # 'Python Programming'

# 查找和替换
s.find("Pro")      # 7(返回索引,找不到返回 -1)
s.index("Pro")     # 7(返回索引,找不到抛异常)
s.replace("Python", "Java")  # 'Java Programming'

# 分割和连接
s.split()          # ['Python', 'Programming'](按空格分割)
s.split("n")       # ['Pytho', ' Programm', 'g']
",".join(["a", "b", "c"])  # 'a,b,c'

# 去除空白
"  hello  ".strip()    # 'hello'
"  hello  ".lstrip()   # 'hello  '
"  hello  ".rstrip()   # '  hello'

# 判断
s.startswith("Py")  # True
s.endswith("ing")   # True
s.isdigit()         # False(是否全为数字)
s.isalpha()         # False(是否全为字母)

# 索引和切片
s[0]        # 'P'(第一个字符)
s[-1]       # 'g'(最后一个字符)
s[0:6]      # 'Python'(切片:从索引 0 到 6,不包含 6)
s[:6]       # 'Python'(从开头到索引 6)
s[7:]       # 'Programming'(从索引 7 到结尾)
s[::2]      # 'Pto rgamn'(步长为 2)
s[::-1]     # 'gnimmargorP nohtyP'(反转字符串)

2.4 布尔类型

# 布尔值
is_true = True
is_false = False

# 布尔运算
result = True and False  # False
result = True or False   # True
result = not True        # False

# 其他类型转布尔
bool(1)      # True(非零数字为 True)
bool(0)      # False
bool("")     # False(空字符串为 False)
bool("abc")  # True(非空字符串为 True)
bool([])     # False(空列表为 False)
bool([1,2])  # True(非空列表为 True)
bool(None)   # False(None 为 False)

# 布尔值在条件判断中的应用
if name:  # 等价于 if name != "" and name is not None
    print("有名字")

2.5 None 类型

# None 表示"无值"或"空值"
value = None

# 检查是否为 None
if value is None:
    print("值为空")

# None 与其他值的比较
None == None   # True
None is None   # True(推荐用 is 比较)

2.6 类型检查和转换

# 类型检查
type(10)           # <class 'int'>
type("hello")      # <class 'str'>
isinstance(10, int)  # True(推荐用 isinstance)

# 类型转换
int("123")         # 123
float("3.14")      # 3.14
str(123)           # '123'
bool(1)            # True
list("abc")        # ['a', 'b', 'c']
tuple([1, 2, 3])   # (1, 2, 3)

2.7 练习题

练习 2.1:创建一个变量存储你的信息(姓名、年龄、城市),并用 f-string 格式化输出

查看答案
name = "张三"
age = 25
city = "北京"

print(f"姓名: {name}, 年龄: {age}, 城市: {city}")

练习 2.2:编写程序,计算圆的面积(半径 = 5,π = 3.14159)

查看答案
radius = 5
pi = 3.14159
area = pi * radius ** 2

print(f"半径为 {radius} 的圆的面积是: {area:.2f}")

练习 2.3:字符串操作练习

  • 给定字符串 " Hello, World! "
  • 去除首尾空格
  • 转换为小写
  • 替换 "World" 为 "Python"
  • 反转字符串
查看答案
s = "  Hello, World!  "
print(f"原始字符串: '{s}'")  # 原始字符串: '  Hello, World!  '

s = s.strip()           # 去除首尾空格
print(f"去除空格后: '{s}'")  # 去除空格后: 'Hello, World!'

s = s.lower()           # 转小写
print(f"转小写后: '{s}'")  # 转小写后: 'hello, world!'

s = s.replace("world", "python")  # 替换
print(f"替换后: '{s}'")  # 替换后: 'hello, python!'

s = s[::-1]             # 反转
print(f"反转后: '{s}'")  # 反转后: '!nohtyp ,olleh'

三、容器类型:list / tuple / dict / set

Python 提供了四种常用的容器类型,用于存储多个数据。

3.1 列表 list(可变、有序)

特点:有序、可变、可重复元素

创建列表

# 空列表
empty = []
empty = list()

# 包含元素的列表
nums = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]  # 可以混合类型
nested = [[1, 2], [3, 4]]  # 嵌套列表

访问元素

nums = [10, 20, 30, 40, 50]

# 索引访问(从 0 开始)
nums[0]    # 10(第一个元素)
nums[2]    # 30(第三个元素)
nums[-1]   # 50(最后一个元素)
nums[-2]   # 40(倒数第二个)

# 切片(slice)
nums[1:3]      # [20, 30](索引 1 到 2,不包含 3)
nums[:3]       # [10, 20, 30](前三个)
nums[2:]       # [30, 40, 50](从索引 2 开始)
nums[::2]      # [10, 30, 50](步长为 2)
nums[::-1]     # [50, 40, 30, 20, 10](反转)

修改列表

nums = [1, 2, 3]

# 添加元素
nums.append(4)           # [1, 2, 3, 4](末尾添加)
nums.insert(1, 10)       # [1, 10, 2, 3, 4](索引 1 处插入)
nums.extend([5, 6])     # [1, 10, 2, 3, 4, 5, 6](扩展列表)

# 修改元素
nums[0] = 100           # [100, 10, 2, 3, 4, 5, 6]

# 删除元素
nums.remove(10)         # 删除第一个值为 10 的元素
del nums[0]             # 删除索引 0 的元素
nums.pop()              # 删除并返回最后一个元素
nums.pop(1)             # 删除并返回索引 1 的元素

列表常用方法

nums = [3, 1, 4, 1, 5, 9, 2, 6]

# 查找
nums.index(4)           # 2(返回第一个 4 的索引)
nums.count(1)           # 2(统计 1 出现的次数)
4 in nums               # True(检查元素是否存在)

# 排序
nums.sort()             # 原地排序:[1, 1, 2, 3, 4, 5, 6, 9]
nums.sort(reverse=True) # 降序排序
sorted_nums = sorted(nums)  # 返回新列表,不修改原列表

# 反转
nums.reverse()          # 原地反转
reversed_nums = nums[::-1]  # 返回新列表

# 长度
len(nums)               # 8

遍历列表

nums = [1, 2, 3, 4, 5]

# 方式 1:直接遍历元素
for num in nums:
    print(num)

# 方式 2:遍历索引
for i in range(len(nums)):
    print(f"索引 {i}: {nums[i]}")

# 方式 3:同时获取索引和值(推荐)
for i, num in enumerate(nums):
    print(f"索引 {i}: {num}")

# 方式 4:列表推导式(后面会讲)
squares = [x**2 for x in nums]

3.2 元组 tuple(不可变、有序)

特点:有序、不可变、可重复元素(一旦创建不能修改)

创建元组

# 空元组
empty = ()
empty = tuple()

# 包含元素的元组
point = (10, 20)
single = (42,)  # 注意:单个元素需要逗号
mixed = (1, "hello", 3.14)

# 也可以不用括号(不推荐)
point = 10, 20

访问元素

point = (10, 20, 30)

point[0]    # 10
point[-1]   # 30
point[1:3]  # (20, 30)(切片)

解包(unpacking)

# 基本解包
x, y = (10, 20)
print(x, y)  # 10 20

# 扩展解包
first, *middle, last = (1, 2, 3, 4, 5)
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

# 交换变量(元组解包的应用)
a, b = 10, 20
a, b = b, a  # 交换:a=20, b=10

元组常用操作

t = (1, 2, 3, 2, 4)

len(t)        # 5
t.count(2)    # 2(统计元素出现次数)
t.index(3)    # 2(返回元素索引)
3 in t        # True

# 元组不可变,但可以连接
t1 = (1, 2)
t2 = (3, 4)
t3 = t1 + t2  # (1, 2, 3, 4)

使用场景

  • 作为字典的键(因为不可变)
  • 函数返回多个值
  • 保护数据不被修改

3.3 字典 dict(键值对,无序)

特点:键值对存储、无序(Python 3.7+ 保持插入顺序)、键必须不可变

创建字典

# 空字典
empty = {}
empty = dict()

# 包含键值对
user = {
    "name": "Tom",
    "age": 20,
    "city": "Beijing"
}

# 使用 dict() 构造函数
user = dict(name="Tom", age=20)
user = dict([("name", "Tom"), ("age", 20)])

访问和修改

user = {"name": "Tom", "age": 20}

# 访问
user["name"]              # 'Tom'
user.get("age")          # 20
user.get("email", "N/A") # 'N/A'(键不存在时返回默认值)

# 修改
user["age"] = 21         # 修改值
user["email"] = "tom@example.com"  # 添加新键值对

# 删除
del user["age"]          # 删除键值对
email = user.pop("email")  # 删除并返回值
user.clear()             # 清空字典

字典常用方法

user = {"name": "Tom", "age": 20, "city": "Beijing"}

# 获取所有键、值、键值对
user.keys()      # dict_keys(['name', 'age', 'city'])
user.values()    # dict_values(['Tom', 20, 'Beijing'])
user.items()     # dict_items([('name', 'Tom'), ('age', 20), ...])

# 转换为列表
list(user.keys())   # ['name', 'age', 'city']

# 检查键是否存在
"name" in user      # True
"email" in user     # False

# 更新字典
user.update({"age": 21, "email": "tom@example.com"})

# 长度
len(user)           # 3

遍历字典

user = {"name": "Tom", "age": 20, "city": "Beijing"}

# 遍历键
for key in user:
    print(key, user[key])

# 遍历键值对(推荐)
for key, value in user.items():
    print(f"{key}: {value}")

# 遍历值
for value in user.values():
    print(value)

字典推导式

# 创建平方字典
squares = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 过滤
even_squares = {x: x**2 for x in range(5) if x % 2 == 0}
# {0: 0, 2: 4, 4: 16}

3.4 集合 set(去重、无序)

特点:无序、不重复、可变(frozenset 不可变)

创建集合

# 空集合(注意:不能用 {},那是空字典)
empty = set()

# 包含元素的集合
s = {1, 2, 3, 4}
s = set([1, 2, 3, 3, 4])  # {1, 2, 3, 4}(自动去重)

# 从字符串创建
s = set("hello")  # {'h', 'e', 'l', 'o'}(去重)

集合操作

s = {1, 2, 3, 4}

# 添加元素
s.add(5)           # {1, 2, 3, 4, 5}
s.update([5, 6, 7])  # {1, 2, 3, 4, 5, 6, 7}

# 删除元素
s.remove(5)        # 删除 5,不存在会报错
s.discard(10)      # 删除 10,不存在不报错
s.pop()            # 删除并返回任意一个元素
s.clear()          # 清空集合

# 检查成员
3 in s             # True
10 in s            # False

集合运算

a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

# 并集
a | b              # {1, 2, 3, 4, 5, 6}
a.union(b)         # 等价写法

# 交集
a & b              # {3, 4}
a.intersection(b)  # 等价写法

# 差集
a - b              # {1, 2}(在 a 中但不在 b 中)
a.difference(b)    # 等价写法

# 对称差集(异或)
a ^ b              # {1, 2, 5, 6}(只在其中一个集合中)
a.symmetric_difference(b)  # 等价写法

# 子集和超集
{1, 2}.issubset(a)     # True
a.issuperset({1, 2})   # True

集合推导式

# 创建偶数集合
evens = {x for x in range(10) if x % 2 == 0}
# {0, 2, 4, 6, 8}

3.5 容器类型选择指南

类型 有序 可变 重复 使用场景
list 需要有序、可修改的序列
tuple 不可变序列,作为字典键
dict ✅* ❌键 键值对映射
set 去重、集合运算

*Python 3.7+ 字典保持插入顺序

3.6 练习题

练习 3.1:列表操作

  • 创建一个包含 1-10 的列表
  • 计算列表所有元素的和
  • 找出列表中的最大值和最小值
  • 将列表反转
查看答案
# 创建列表
nums = list(range(1, 11))  # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 计算和
total = sum(nums)
print(f"和: {total}")  # 55

# 最大值和最小值
print(f"最大值: {max(nums)}")  # 10
print(f"最小值: {min(nums)}")  # 1

# 反转
nums.reverse()  # 或 nums[::-1]
print(nums)  # [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

练习 3.2:字典操作

  • 创建一个学生信息字典(姓名、年龄、成绩)
  • 添加新的键值对(班级)
  • 遍历并打印所有信息
  • 计算平均成绩
查看答案
# 创建字典
student = {
    "name": "张三",
    "age": 18,
    "scores": [85, 90, 88]
}

# 添加班级
student["class"] = "高三(1)班"

# 遍历打印
for key, value in student.items():
    print(f"{key}: {value}")

# 计算平均成绩
avg_score = sum(student["scores"]) / len(student["scores"])
print(f"平均成绩: {avg_score:.2f}")  # 87.67

练习 3.3:集合操作

  • 有两个列表:[1, 2, 3, 4, 5][4, 5, 6, 7, 8]
  • 找出它们的交集、并集和差集
查看答案
a = [1, 2, 3, 4, 5]
b = [4, 5, 6, 7, 8]

set_a = set(a)
set_b = set(b)

# 交集
intersection = set_a & set_b
print(f"交集: {intersection}")  # {4, 5}

# 并集
union = set_a | set_b
print(f"并集: {union}")  # {1, 2, 3, 4, 5, 6, 7, 8}

# 差集
difference = set_a - set_b
print(f"差集: {difference}")  # {1, 2, 3}

练习 3.4:综合练习 编写一个程序,统计一段文本中每个单词出现的次数。

查看答案
text = "python is great python is fun python is powerful"

# 方法 1:使用字典
word_count = {}
words = text.split()

for word in words:
    word_count[word] = word_count.get(word, 0) + 1

print(word_count)
# {'python': 3, 'is': 3, 'great': 1, 'fun': 1, 'powerful': 1}

# 方法 2:使用 collections.Counter(更简洁)
from collections import Counter
word_count = Counter(text.split())
print(dict(word_count))

四、运算符

Python 提供了丰富的运算符,用于各种计算和比较操作。

4.1 算术运算符

# 基本算术运算
a = 10
b = 3

a + b      # 13(加法)
a - b      # 7(减法)
a * b      # 30(乘法)
a / b      # 3.333...(除法,返回浮点数)
a // b     # 3(整除,向下取整)
a % b      # 1(取余/模运算)
a ** b     # 1000(幂运算,10 的 3 次方)

# 字符串和列表的运算
"Hello" + " " + "World"  # 'Hello World'(字符串连接)
[1, 2] + [3, 4]          # [1, 2, 3, 4](列表连接)
"Hi" * 3                  # 'HiHiHi'(字符串重复)
[1, 2] * 3                # [1, 2, 1, 2, 1, 2](列表重复)

示例

# 计算圆的面积
radius = 5
pi = 3.14159
area = pi * radius ** 2
print(f"面积: {area:.2f}")  # 面积: 78.54

# 整除和取余的应用
total_minutes = 125
hours = total_minutes // 60    # 2(小时)
minutes = total_minutes % 60   # 5(分钟)
print(f"{hours}小时{minutes}分钟")  # 2小时5分钟

4.2 比较运算符

返回布尔值(True/False)

a = 10
b = 20

a == b     # False(等于)
a != b     # True(不等于)
a < b      # True(小于)
a > b      # False(大于)
a <= b     # True(小于等于)
a >= b     # False(大于等于)

# 字符串比较(按字典序)
"apple" < "banana"  # True
"abc" == "abc"      # True

# 链式比较
5 < 10 < 20         # True(等价于 5 < 10 and 10 < 20)

示例

# 判断成绩等级
score = 85

if score >= 90:
    grade = "优秀"
elif score >= 80:
    grade = "良好"
elif score >= 60:
    grade = "及格"
else:
    grade = "不及格"

print(f"成绩: {score}, 等级: {grade}")

4.3 逻辑运算符

# and(与):两个都为 True 才返回 True
True and True    # True
True and False   # False
False and False  # False

# or(或):至少一个为 True 就返回 True
True or False    # True
False or False   # False

# not(非):取反
not True         # False
not False        # True

# 实际应用
age = 20
has_license = True

if age >= 18 and has_license:
    print("可以开车")

# 短路求值
x = 0
if x != 0 and 10 / x > 1:  # 不会执行除法,因为 x != 0 为 False
    print("安全")

示例

# 判断年份是否为闰年
year = 2024
is_leap = (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
print(f"{year}年是闰年: {is_leap}")  # True

4.4 成员运算符

# in:检查元素是否在容器中
3 in [1, 2, 3, 4]        # True
"py" in "python"         # True
"name" in {"name": "Tom"}  # True(检查键)

# not in:检查元素是否不在容器中
10 not in [1, 2, 3]      # True

示例

# 检查用户名是否有效
forbidden = ["admin", "root", "test"]
username = "user123"

if username not in forbidden:
    print("用户名有效")
else:
    print("用户名无效")

4.5 身份运算符

# is:检查两个对象是否是同一个对象(内存地址)
# ==:检查两个对象的值是否相等

a = [1, 2, 3]
b = [1, 2, 3]
c = a

a == b      # True(值相等)
a is b      # False(不是同一个对象)
a is c      # True(是同一个对象)

# 小整数和字符串的缓存(Python 优化)
x = 100
y = 100
x is y      # True(小整数被缓存)

# None 的比较
value = None
value is None    # True(推荐)
value == None    # True(不推荐)

4.6 赋值运算符

x = 10

# 基本赋值
x = 5

# 复合赋值
x += 3      # x = x + 3,结果:8
x -= 2      # x = x - 2,结果:6
x *= 2      # x = x * 2,结果:12
x /= 3      # x = x / 3,结果:4.0
x //= 2     # x = x // 2,结果:2.0
x %= 2      # x = x % 2,结果:0.0
x **= 3     # x = x ** 3,结果:0.0

# 多重赋值
a = b = c = 0        # 三个变量都赋值为 0
x, y = 10, 20        # x=10, y=20
x, y = y, x          # 交换 x 和 y

4.7 运算符优先级

从高到低(部分):

  1. () - 括号
  2. ** - 幂运算
  3. *, /, //, % - 乘除
  4. +, - - 加减
  5. <, <=, >, >=, ==, != - 比较
  6. not - 逻辑非
  7. and - 逻辑与
  8. or - 逻辑或

示例

# 使用括号明确优先级
result = (2 + 3) * 4      # 20(先算括号)
result = 2 + 3 * 4        # 14(先算乘法)

# 复杂表达式
x = 5
y = 10
z = (x + y) * 2 / 3      # 10.0

4.8 练习题

练习 4.1:算术运算

  • 计算 (10 + 5) * 3 - 8 / 2 的结果
  • 计算 2 的 10 次方
  • 将 1234 秒转换为小时、分钟、秒
查看答案
# 1. 计算表达式
result = (10 + 5) * 3 - 8 / 2
print(f"结果: {result}")  # 41.0

# 2. 2 的 10 次方
power = 2 ** 10
print(f"2^10 = {power}")  # 1024

# 3. 时间转换
total_seconds = 1234
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
print(f"{hours}小时{minutes}分钟{seconds}秒")  # 0小时20分钟34秒

练习 4.2:逻辑运算 编写程序判断一个数是否在 1-100 之间,且是偶数。

查看答案
num = 42

# 方法 1
if 1 <= num <= 100 and num % 2 == 0:
    print(f"{num} 在 1-100 之间且是偶数")
else:
    print(f"{num} 不符合条件")

# 方法 2(更清晰)
is_in_range = 1 <= num <= 100
is_even = num % 2 == 0

if is_in_range and is_even:
    print(f"{num} 在 1-100 之间且是偶数")

练习 4.3:成员运算 给定一个列表 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],找出所有能被 3 整除的数。

查看答案
numbers = list(range(1, 11))
divisible_by_3 = []

for num in numbers:
    if num % 3 == 0:
        divisible_by_3.append(num)

print(f"能被 3 整除的数: {divisible_by_3}")  # [3, 6, 9]

# 或使用列表推导式
divisible_by_3 = [num for num in numbers if num % 3 == 0]

练习 4.4:综合练习 编写一个简单的计算器,支持加、减、乘、除四种运算。

查看答案
def calculator(a, b, operator):
    """简单计算器"""
    if operator == "+":
        return a + b
    elif operator == "-":
        return a - b
    elif operator == "*":
        return a * b
    elif operator == "/":
        if b != 0:
            return a / b
        else:
            return "错误:除数不能为 0"
    else:
        return "错误:不支持的运算符"

# 测试
print(calculator(10, 5, "+"))  # 15
print(calculator(10, 5, "-"))  # 5
print(calculator(10, 5, "*"))  # 50
print(calculator(10, 5, "/"))  # 2.0
print(calculator(10, 0, "/"))  # 错误:除数不能为 0

五、流程控制:if / for / while

流程控制是编程的核心,用于控制程序的执行顺序。

5.1 条件语句 if / elif / else

基本语法

# 单分支
if condition:
    # 代码块
    pass

# 双分支
if condition:
    # 条件为 True 时执行
    pass
else:
    # 条件为 False 时执行
    pass

# 多分支
if condition1:
    pass
elif condition2:
    pass
elif condition3:
    pass
else:
    pass

示例

# 判断年龄阶段
age = 20

if age < 18:
    print("未成年")
elif age < 60:
    print("成年人")
else:
    print("老年人")

# 判断成绩等级
score = 85

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
elif score >= 60:
    grade = "D"
else:
    grade = "F"

print(f"成绩: {score}, 等级: {grade}")

# 嵌套 if
x = 10
y = 5

if x > 0:
    if y > 0:
        print("x 和 y 都大于 0")
    else:
        print("x > 0 但 y <= 0")
else:
    print("x <= 0")

# 简化写法(逻辑运算符)
if x > 0 and y > 0:
    print("x 和 y 都大于 0")

三元运算符(条件表达式):

# 基本语法:value_if_true if condition else value_if_false

age = 20
status = "成年人" if age >= 18 else "未成年人"
print(status)  # 成年人

# 嵌套使用
score = 85
grade = "优秀" if score >= 90 else "良好" if score >= 80 else "及格" if score >= 60 else "不及格"
print(grade)  # 良好

5.2 for 循环

基本语法

# 遍历序列
for item in sequence:
    # 代码块
    pass

遍历不同类型

# 遍历列表
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
    print(fruit)

# 遍历字符串
for char in "Python":
    print(char)

# 遍历字典
user = {"name": "Tom", "age": 20, "city": "Beijing"}

# 遍历键
for key in user:
    print(key, user[key])

# 遍历键值对(推荐)
for key, value in user.items():
    print(f"{key}: {value}")

# 遍历值
for value in user.values():
    print(value)

range() 函数

# range(stop):0 到 stop-1
for i in range(5):
    print(i)  # 0, 1, 2, 3, 4

# range(start, stop):start 到 stop-1
for i in range(2, 5):
    print(i)  # 2, 3, 4

# range(start, stop, step):指定步长
for i in range(0, 10, 2):
    print(i)  # 0, 2, 4, 6, 8

# 反向遍历
for i in range(10, 0, -1):
    print(i)  # 10, 9, 8, ..., 1

enumerate() 函数

# 同时获取索引和值
fruits = ["apple", "banana", "orange"]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
# 输出:
# 0: apple
# 1: banana
# 2: orange

# 指定起始索引
for index, fruit in enumerate(fruits, start=1):
    print(f"{index}: {fruit}")
# 输出:
# 1: apple
# 2: banana
# 3: orange

zip() 函数

# 并行遍历多个序列
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]

for name, age in zip(names, ages):
    print(f"{name} is {age} years old")
# 输出:
# Alice is 25 years old
# Bob is 30 years old
# Charlie is 35 years old

5.3 while 循环

基本语法

while condition:
    # 代码块
    # 需要修改 condition,否则会无限循环
    pass

示例

# 计数循环
count = 0
while count < 5:
    print(count)
    count += 1
# 输出:0, 1, 2, 3, 4

# 用户输入循环
# while True:
#     user_input = input("请输入(输入 'quit' 退出): ")
#     if user_input == 'quit':
#         break
#     print(f"你输入了: {user_input}")

# 计算阶乘
n = 5
factorial = 1
i = 1

while i <= n:
    factorial *= i
    i += 1

print(f"{n}! = {factorial}")  # 120

5.4 break 和 continue

break:跳出循环

# 找到第一个偶数就停止
numbers = [1, 3, 5, 8, 9, 10]

for num in numbers:
    if num % 2 == 0:
        print(f"找到第一个偶数: {num}")
        break
    print(f"{num} 是奇数")
# 输出:
# 1 是奇数
# 3 是奇数
# 5 是奇数
# 找到第一个偶数: 8

continue:跳过当前迭代,继续下一次

# 只打印偶数
for num in range(10):
    if num % 2 != 0:
        continue  # 跳过奇数
    print(num)
# 输出:0, 2, 4, 6, 8

else 子句(for/while 循环):

# for/while 循环可以带 else,在循环正常结束时执行(不是 break 退出)
for i in range(5):
    print(i)
else:
    print("循环正常结束")

# 如果 break 退出,else 不执行
for i in range(5):
    if i == 3:
        break
    print(i)
else:
    print("这行不会执行")

5.5 嵌套循环

# 打印乘法表
for i in range(1, 10):
    for j in range(1, i + 1):
        print(f"{j}×{i}={i*j}", end="\t")
    print()  # 换行

# 查找二维列表中的元素
matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

target = 5
found = False

for row in matrix:
    for element in row:
        if element == target:
            print(f"找到 {target}")
            found = True
            break
    if found:
        break

5.6 练习题

练习 5.1:条件语句 编写程序,判断一个年份是否为闰年。

  • 能被 4 整除但不能被 100 整除,或者
  • 能被 400 整除
查看答案
year = 2024

if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
    print(f"{year} 年是闰年")
else:
    print(f"{year} 年不是闰年")

# 或使用函数
def is_leap_year(year):
    return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)

print(is_leap_year(2024))  # True
print(is_leap_year(1900))   # False
print(is_leap_year(2000))   # True

练习 5.2:for 循环 计算 1 到 100 之间所有偶数的和。

查看答案
# 方法 1:使用 range
total = 0
for i in range(2, 101, 2):  # 从 2 开始,步长为 2
    total += i
print(f"偶数和: {total}")  # 2550

# 方法 2:使用 if 判断
total = 0
for i in range(1, 101):
    if i % 2 == 0:
        total += i
print(f"偶数和: {total}")  # 2550

# 方法 3:使用 sum 和 range
total = sum(range(2, 101, 2))
print(f"偶数和: {total}")  # 2550

练习 5.3:while 循环 编写一个猜数字游戏:

  • 程序随机生成一个 1-100 的数字
  • 用户输入猜测的数字
  • 提示用户猜大了或猜小了
  • 猜对后显示猜了多少次
查看答案
import random

# 生成随机数
target = random.randint(1, 100)
attempts = 0

print("欢迎来到猜数字游戏!")
print("我已经想好了一个 1-100 之间的数字,试试猜出来吧!")

while True:
    try:
        guess = int(input("请输入你的猜测: "))
        attempts += 1

        if guess < target:
            print("猜小了!再试试。")
        elif guess > target:
            print("猜大了!再试试。")
        else:
            print(f"恭喜你!猜对了!你用了 {attempts} 次。")
            break
    except ValueError:
        print("请输入一个有效的数字!")

练习 5.4:嵌套循环 打印一个由 * 组成的三角形:

*
**
***
****
*****
查看答案
# 方法 1:使用嵌套循环
n = 5
for i in range(1, n + 1):
    for j in range(i):
        print("*", end="")
    print()  # 换行

# 方法 2:使用字符串乘法
n = 5
for i in range(1, n + 1):
    print("*" * i)

# 方法 3:使用列表推导式
print("\n".join(["*" * i for i in range(1, 6)]))

练习 5.5:综合练习 编写程序,找出 1-100 之间的所有质数(只能被 1 和自身整除的数)。

查看答案
def is_prime(n):
    """判断一个数是否为质数"""
    if n < 2:
        return False
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False
    return True

# 找出所有质数
primes = []
for num in range(2, 101):
    if is_prime(num):
        primes.append(num)

print(f"1-100 之间的质数: {primes}")
print(f"共有 {len(primes)} 个质数")

六、函数(def) & 默认参数 / 可变参数

函数是组织代码的重要方式,可以重复使用代码块。

6.1 基础函数定义

基本语法

def function_name(parameters):
    """函数文档字符串(可选)"""
    # 函数体
    return value  # 可选,不写 return 返回 None

示例

# 简单函数
def greet(name):
    print(f"Hello, {name}!")

greet("Tom")  # Hello, Tom!

# 带返回值的函数
def add(x, y):
    return x + y

result = add(3, 5)
print(result)  # 8

# 无返回值函数
def print_info(name, age):
    print(f"姓名: {name}, 年龄: {age}")

print_info("Alice", 25)  # 姓名: Alice, 年龄: 25

# 多个返回值(返回元组)
def get_name_and_age():
    return "Tom", 20

name, age = get_name_and_age()
print(f"{name}, {age}")  # Tom, 20

函数文档字符串

def calculate_area(radius):
    """
    计算圆的面积

    参数:
        radius (float): 圆的半径

    返回:
        float: 圆的面积
    """
    return 3.14159 * radius ** 2

# 查看文档字符串
print(calculate_area.__doc__)
help(calculate_area)

6.2 函数参数

位置参数

def power(base, exponent):
    return base ** exponent

result = power(2, 3)  # 8(按位置传递)

关键字参数

# 使用参数名传递(顺序可以改变)
result = power(exponent=3, base=2)  # 8

# 混合使用(位置参数必须在关键字参数之前)
result = power(2, exponent=3)  # 8

默认参数

def greet(name, msg="你好", punctuation="!"):
    print(f"{msg}, {name}{punctuation}")

greet("Tom")                    # 你好, Tom!
greet("Tom", "早上好")          # 早上好, Tom!
greet("Tom", "Hi", "?")         # Hi, Tom?

# 注意:默认参数必须是不可变对象
# 错误示例
def add_item(item, items=[]):  # 危险!
    items.append(item)
    return items

# 正确做法
def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

可变位置参数 *args

def sum_all(*args):
    """计算所有参数的和"""
    total = 0
    for num in args:
        total += num
    return total

print(sum_all(1, 2, 3))        # 6
print(sum_all(1, 2, 3, 4, 5))  # 15

# args 是一个元组
def print_args(*args):
    print(f"参数类型: {type(args)}")  # <class 'tuple'>
    print(f"参数: {args}")

print_args(1, 2, 3)  # 参数: (1, 2, 3)

可变关键字参数 `kwargs`**:

def show_info(**kwargs):
    """打印所有关键字参数"""
    for key, value in kwargs.items():
        print(f"{key}: {value}")

show_info(name="Tom", age=20, city="Beijing")
# 输出:
# name: Tom
# age: 20
# city: Beijing

# kwargs 是一个字典
def create_user(**kwargs):
    user = {}
    for key, value in kwargs.items():
        user[key] = value
    return user

user = create_user(name="Tom", age=20)
print(user)  # {'name': 'Tom', 'age': 20}

参数组合

# 参数顺序:位置参数 -> *args -> 关键字参数 -> **kwargs
def complex_func(a, b, *args, c=10, **kwargs):
    print(f"a={a}, b={b}")
    print(f"args={args}")
    print(f"c={c}")
    print(f"kwargs={kwargs}")

complex_func(1, 2, 3, 4, c=20, x=100, y=200)
# 输出:
# a=1, b=2
# args=(3, 4)
# c=20
# kwargs={'x': 100, 'y': 200}

6.3 函数作用域

局部变量和全局变量

# 全局变量
x = 10

def func():
    # 局部变量
    y = 20
    print(f"局部 y: {y}")
    print(f"全局 x: {x}")  # 可以读取全局变量

func()
print(f"全局 x: {x}")
# print(y)  # 错误:y 是局部变量

# 修改全局变量
def modify_global():
    global x  # 声明使用全局变量
    x = 30

modify_global()
print(x)  # 30

nonlocal 关键字

def outer():
    x = 10

    def inner():
        nonlocal x  # 使用外层函数的变量
        x = 20
        print(f"inner: {x}")

    inner()
    print(f"outer: {x}")

outer()
# 输出:
# inner: 20
# outer: 20

6.4 Lambda 函数(匿名函数)

# 基本语法:lambda 参数: 表达式
add = lambda x, y: x + y
print(add(3, 5))  # 8

# 常用于高阶函数
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares)  # [1, 4, 9, 16, 25]

# 排序
students = [("Alice", 20), ("Bob", 18), ("Charlie", 22)]
students.sort(key=lambda s: s[1])  # 按年龄排序
print(students)  # [('Bob', 18), ('Alice', 20), ('Charlie', 22)]

6.5 递归函数

# 计算阶乘
def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))  # 120

# 斐波那契数列
def fibonacci(n):
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(10))  # 55

# 注意:递归可能导致栈溢出,需要设置递归深度限制
import sys
sys.setrecursionlimit(1000)

6.6 函数作为对象

# 函数可以赋值给变量
def greet(name):
    return f"Hello, {name}!"

say_hello = greet
print(say_hello("Tom"))  # Hello, Tom!

# 函数可以作为参数传递
def apply_func(func, value):
    return func(value)

def square(x):
    return x ** 2

result = apply_func(square, 5)
print(result)  # 25

# 函数可以作为返回值
def get_multiplier(n):
    def multiplier(x):
        return x * n
    return multiplier

double = get_multiplier(2)
triple = get_multiplier(3)

print(double(5))  # 10
print(triple(5))  # 15

6.7 练习题

练习 6.1:基础函数 编写一个函数,计算两个数的最大公约数(GCD)。

查看答案
def gcd(a, b):
    """计算最大公约数(欧几里得算法)"""
    while b:
        a, b = b, a % b
    return a

print(gcd(48, 18))  # 6
print(gcd(100, 25))  # 25

# 递归版本
def gcd_recursive(a, b):
    if b == 0:
        return a
    return gcd_recursive(b, a % b)

print(gcd_recursive(48, 18))  # 6

练习 6.2:默认参数 编写一个函数 format_name,接受姓和名,返回格式化的全名。默认格式为 "名 姓",但可以通过参数改变。

查看答案
def format_name(first_name, last_name, reverse=False):
    """
    格式化姓名

    参数:
        first_name: 名
        last_name: 姓
        reverse: 如果为 True,返回 "姓 名",否则返回 "名 姓"
    """
    if reverse:
        return f"{last_name} {first_name}"
    else:
        return f"{first_name} {last_name}"

print(format_name("三", "张"))           # 三 张
print(format_name("三", "张", True))    # 张 三

练习 6.3:可变参数 编写一个函数,接受任意数量的数字,返回它们的平均值。

查看答案
def average(*args):
    """计算平均值"""
    if len(args) == 0:
        return 0
    return sum(args) / len(args)

print(average(1, 2, 3, 4, 5))  # 3.0
print(average(10, 20, 30))     # 20.0
print(average())               # 0

练习 6.4:递归函数 编写一个递归函数,计算列表所有元素的和。

查看答案
def list_sum(lst):
    """递归计算列表和"""
    if len(lst) == 0:
        return 0
    return lst[0] + list_sum(lst[1:])

print(list_sum([1, 2, 3, 4, 5]))  # 15

# 更高效的版本(避免切片)
def list_sum_efficient(lst, index=0):
    if index >= len(lst):
        return 0
    return lst[index] + list_sum_efficient(lst, index + 1)

print(list_sum_efficient([1, 2, 3, 4, 5]))  # 15

练习 6.5:综合练习 编写一个函数,接受学生信息(使用 **kwargs),返回格式化的学生信息字符串。

查看答案
def format_student(**kwargs):
    """格式化学生信息"""
    required = ["name", "age"]

    # 检查必需字段
    for field in required:
        if field not in kwargs:
            return f"错误:缺少必需字段 '{field}'"

    # 格式化输出
    info = f"姓名: {kwargs['name']}, 年龄: {kwargs['age']}"

    # 添加可选字段
    if "grade" in kwargs:
        info += f", 年级: {kwargs['grade']}"
    if "score" in kwargs:
        info += f", 成绩: {kwargs['score']}"

    return info

print(format_student(name="张三", age=18))
# 姓名: 张三, 年龄: 18

print(format_student(name="李四", age=19, grade="高三", score=95))
# 姓名: 李四, 年龄: 19, 年级: 高三, 成绩: 95

七、模块与包(import)

模块是包含 Python 代码的文件,包是包含多个模块的目录。

7.1 导入标准库

# 导入整个模块
import math
print(math.sqrt(16))  # 4.0
print(math.pi)        # 3.141592653589793

# 导入特定函数/类
from datetime import datetime, timedelta
now = datetime.now()
print(now)

# 导入并重命名
import math as m
print(m.sqrt(16))

# 导入所有(不推荐,可能造成命名冲突)
from math import *
print(sqrt(16))

常用标准库

# os - 操作系统接口
import os
print(os.getcwd())  # 当前工作目录
print(os.listdir('.'))  # 列出目录内容

# sys - 系统相关
import sys
print(sys.version)  # Python 版本
print(sys.path)     # 模块搜索路径

# json - JSON 处理
import json
data = {"name": "Tom", "age": 20}
json_str = json.dumps(data)  # 转为 JSON 字符串
data = json.loads(json_str)  # 解析 JSON

# random - 随机数
import random
print(random.randint(1, 10))  # 随机整数
print(random.choice([1, 2, 3]))  # 随机选择

# datetime - 日期时间
from datetime import datetime, timedelta
now = datetime.now()
tomorrow = now + timedelta(days=1)

7.2 创建和使用模块

文件结构

myproject/
  main.py
  utils.py
  math_utils.py

utils.py(模块文件):

"""工具函数模块"""

def greet(name):
    """问候函数"""
    return f"Hello, {name}!"

def add(x, y):
    """加法函数"""
    return x + y

# 模块级别的变量
PI = 3.14159

# 如果直接运行此文件,执行以下代码
if __name__ == "__main__":
    print("这是 utils 模块")
    print(greet("Test"))

main.py(主程序):

# 导入整个模块
import utils
print(utils.greet("Tom"))
print(utils.add(3, 5))

# 导入特定函数
from utils import greet, add
print(greet("Alice"))
print(add(10, 20))

# 导入并重命名
from utils import greet as say_hello
say_hello("Bob")

7.3 创建包

文件结构

mypackage/
  __init__.py      # 包初始化文件(可以是空文件)
  module1.py
  module2.py
  subpackage/
    __init__.py
    module3.py

init.py(包初始化):

"""mypackage 包"""

# 可以导入子模块,方便使用
from .module1 import function1
from .module2 import function2

# 定义包的版本等
__version__ = "1.0.0"

使用包

# 导入包中的模块
from mypackage import module1
from mypackage.module2 import function2

# 导入子包
from mypackage.subpackage import module3

7.4 模块搜索路径

import sys
print(sys.path)  # Python 搜索模块的路径列表

# 添加自定义路径
sys.path.append('/path/to/your/modules')

7.5 练习题

练习 7.1:创建工具模块 创建一个 string_utils.py 模块,包含以下函数:

  • reverse_string(s): 反转字符串
  • count_words(s): 统计单词数
  • capitalize_words(s): 每个单词首字母大写
查看答案
# string_utils.py
def reverse_string(s):
    """反转字符串"""
    return s[::-1]

def count_words(s):
    """统计单词数"""
    return len(s.split())

def capitalize_words(s):
    """每个单词首字母大写"""
    return ' '.join(word.capitalize() for word in s.split())

# 测试
if __name__ == "__main__":
    test = "hello world python"
    print(reverse_string(test))      # nohtyp dlrow olleh
    print(count_words(test))         # 3
    print(capitalize_words(test))    # Hello World Python
# main.py
from string_utils import reverse_string, count_words, capitalize_words

text = "python is great"
print(reverse_string(text))
print(count_words(text))
print(capitalize_words(text))

练习 7.2:使用标准库 使用 datetime 模块,编写程序计算两个日期之间的天数差。

查看答案
from datetime import datetime, date

def days_between(date1_str, date2_str):
    """计算两个日期之间的天数"""
    date1 = datetime.strptime(date1_str, "%Y-%m-%d")
    date2 = datetime.strptime(date2_str, "%Y-%m-%d")
    delta = abs((date2 - date1).days)
    return delta

print(days_between("2024-01-01", "2024-12-31"))  # 365

# 更简单的方法
def days_between_simple(date1, date2):
    """使用 date 对象"""
    return abs((date2 - date1).days)

d1 = date(2024, 1, 1)
d2 = date(2024, 12, 31)
print(days_between_simple(d1, d2))  # 365

八、异常处理 try / except / finally

异常处理让程序在遇到错误时能够优雅地处理,而不是崩溃。

8.1 基本异常处理

try/except

# 基本语法
try:
    # 可能出错的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理特定异常
    print("不能除以零!")

# 捕获多个异常
try:
    num = int(input("请输入数字: "))
    result = 10 / num
except ValueError:
    print("输入的不是有效数字")
except ZeroDivisionError:
    print("不能除以零")

捕获异常对象

try:
    x = 1 / 0
except ZeroDivisionError as e:
    print(f"错误: {e}")  # 错误: division by zero
    print(f"错误类型: {type(e)}")  # <class 'ZeroDivisionError'>

捕获所有异常(不推荐,但有时需要):

try:
    # 可能出错的代码
    result = 10 / 0
except Exception as e:
    print(f"发生错误: {e}")

8.2 else 和 finally

else 子句

try:
    result = 10 / 2
except ZeroDivisionError:
    print("除零错误")
else:
    # 没有异常时执行
    print(f"结果: {result}")  # 结果: 5.0

finally 子句

try:
    file = open("data.txt", "r")
    content = file.read()
except FileNotFoundError:
    print("文件不存在")
finally:
    # 无论是否发生异常都会执行
    print("清理工作")
    # file.close()  # 确保文件关闭

8.3 常见异常类型

# ValueError - 值错误
try:
    int("abc")
except ValueError as e:
    print(f"值错误: {e}")

# TypeError - 类型错误
try:
    "hello" + 5
except TypeError as e:
    print(f"类型错误: {e}")

# IndexError - 索引错误
try:
    lst = [1, 2, 3]
    print(lst[10])
except IndexError as e:
    print(f"索引错误: {e}")

# KeyError - 键错误
try:
    d = {"name": "Tom"}
    print(d["age"])
except KeyError as e:
    print(f"键错误: {e}")

# AttributeError - 属性错误
try:
    "hello".append("x")
except AttributeError as e:
    print(f"属性错误: {e}")

8.4 抛出异常

raise 语句

def check_age(age):
    if age < 0:
        raise ValueError("年龄不能为负数")
    if age > 150:
        raise ValueError("年龄不能超过 150")
    return True

try:
    check_age(-5)
except ValueError as e:
    print(f"错误: {e}")  # 错误: 年龄不能为负数

重新抛出异常

try:
    x = 1 / 0
except ZeroDivisionError:
    print("捕获到异常,重新抛出")
    raise  # 重新抛出异常

8.5 自定义异常

# 定义自定义异常
class NegativeNumberError(Exception):
    """负数错误"""
    pass

class TooLargeError(Exception):
    """数值过大错误"""
    def __init__(self, value, max_value):
        self.value = value
        self.max_value = max_value
        self.message = f"值 {value} 超过了最大值 {max_value}"
        super().__init__(self.message)

# 使用自定义异常
def check_number(num, max_val=100):
    if num < 0:
        raise NegativeNumberError("不能是负数")
    if num > max_val:
        raise TooLargeError(num, max_val)
    return True

try:
    check_number(150, 100)
except NegativeNumberError as e:
    print(f"负数错误: {e}")
except TooLargeError as e:
    print(f"过大错误: {e}")  # 过大错误: 值 150 超过了最大值 100

8.6 异常处理最佳实践

# 1. 具体捕获异常,不要用裸露的 except
# 不好
try:
    do_something()
except:  # 捕获所有异常,包括系统退出
    pass

# 好
try:
    do_something()
except (ValueError, TypeError) as e:
    print(f"错误: {e}")

# 2. 使用 finally 确保资源清理
def read_file(filename):
    file = None
    try:
        file = open(filename, "r")
        return file.read()
    except FileNotFoundError:
        print(f"文件 {filename} 不存在")
        return None
    finally:
        if file:
            file.close()

# 3. 使用 with 语句(上下文管理器,见后面章节)
with open("data.txt", "r") as f:
    content = f.read()
# 自动关闭文件

8.7 练习题

练习 8.1:基础异常处理 编写一个安全的除法函数,处理除零错误和类型错误。

查看答案
def safe_divide(a, b):
    """安全除法"""
    try:
        result = a / b
        return result
    except ZeroDivisionError:
        return "错误:除数不能为 0"
    except TypeError:
        return "错误:参数必须是数字"

print(safe_divide(10, 2))    # 5.0
print(safe_divide(10, 0))    # 错误:除数不能为 0
print(safe_divide(10, "2"))  # 错误:参数必须是数字

练习 8.2:文件操作异常 编写程序读取文件,处理文件不存在、权限不足等异常。

查看答案
def read_file_safe(filename):
    """安全读取文件"""
    try:
        with open(filename, "r", encoding="utf-8") as f:
            return f.read()
    except FileNotFoundError:
        return f"错误:文件 {filename} 不存在"
    except PermissionError:
        return f"错误:没有权限读取文件 {filename}"
    except Exception as e:
        return f"未知错误: {e}"

content = read_file_safe("test.txt")
print(content)

练习 8.3:自定义异常 创建一个 BankAccount 类,包含取款方法。如果余额不足,抛出自定义异常 InsufficientFundsError

查看答案
class InsufficientFundsError(Exception):
    """余额不足异常"""
    def __init__(self, balance, amount):
        self.balance = balance
        self.amount = amount
        self.message = f"余额不足:当前余额 {balance},尝试取款 {amount}"
        super().__init__(self.message)

class BankAccount:
    def __init__(self, initial_balance=0):
        self.balance = initial_balance

    def deposit(self, amount):
        """存款"""
        if amount < 0:
            raise ValueError("存款金额不能为负数")
        self.balance += amount
        return self.balance

    def withdraw(self, amount):
        """取款"""
        if amount < 0:
            raise ValueError("取款金额不能为负数")
        if amount > self.balance:
            raise InsufficientFundsError(self.balance, amount)
        self.balance -= amount
        return self.balance

# 测试
account = BankAccount(100)
try:
    account.withdraw(150)
except InsufficientFundsError as e:
    print(e)  # 余额不足:当前余额 100,尝试取款 150

九、面向对象(类 / 继承 / 属性)

1. 定义类

class Person:
    def __init__(self, name, age):
        self.name = name  # 实例属性
        self.age = age

    def say_hello(self):
        print(f"我是 {self.name}, 今年 {self.age} 岁")

p = Person("Tom", 20)
p.say_hello()

2. 继承

class Student(Person):
    def __init__(self, name, age, sid):
        super().__init__(name, age)
        self.sid = sid

    def say_hello(self):
        super().say_hello()
        print(f"学号是 {self.sid}")

3. 类方法 / 静态方法

class User:
    count = 0  # 类属性

    def __init__(self, name):
        self.name = name
        User.count += 1

    @classmethod
    def get_count(cls):
        return cls.count

    @staticmethod
    def hello():
        print("static hello")


User.hello()
print(User.get_count())

十、列表推导式 & 生成器表达式(常用“高级语法糖”)

推导式是 Python 的语法糖,可以简洁地创建列表、字典、集合。

10.1 列表推导式

基本语法[表达式 for 变量 in 可迭代对象]

# 基本用法
nums = [1, 2, 3, 4, 5]
squares = [x * x for x in nums]
print(squares)  # [1, 4, 9, 16, 25]

# 等价于
squares = []
for x in nums:
    squares.append(x * x)

带条件的列表推导式

# 只包含偶数
evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

# 多个条件
result = [x for x in range(20) if x % 2 == 0 if x % 3 == 0]
print(result)  # [0, 6, 12, 18]

# 等价于
result = [x for x in range(20) if x % 2 == 0 and x % 3 == 0]

嵌套循环

# 嵌套列表推导式
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# 等价于
flattened = []
for row in matrix:
    for num in row:
        flattened.append(num)

条件表达式(三元运算符)

# 根据条件选择值
numbers = [1, 2, 3, 4, 5]
result = ["偶数" if x % 2 == 0 else "奇数" for x in numbers]
print(result)  # ['奇数', '偶数', '奇数', '偶数', '奇数']

10.2 字典推导式

基本语法{键: 值 for 变量 in 可迭代对象}

# 创建平方字典
squares = {x: x * x for x in range(5)}
print(squares)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 从列表创建字典
names = ["Alice", "Bob", "Charlie"]
name_lengths = {name: len(name) for name in names}
print(name_lengths)  # {'Alice': 5, 'Bob': 3, 'Charlie': 7}

# 带条件
even_squares = {x: x*x for x in range(10) if x % 2 == 0}
print(even_squares)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

# 反转字典
original = {"a": 1, "b": 2, "c": 3}
reversed_dict = {value: key for key, value in original.items()}
print(reversed_dict)  # {1: 'a', 2: 'b', 3: 'c'}

10.3 集合推导式

基本语法{表达式 for 变量 in 可迭代对象}

# 创建集合
squares = {x * x for x in range(5)}
print(squares)  # {0, 1, 4, 9, 16}(集合,无序)

# 去重
words = ["hello", "world", "hello", "python"]
unique_lengths = {len(word) for word in words}
print(unique_lengths)  # {5, 6}(去重后的长度)

10.4 生成器表达式

基本语法(表达式 for 变量 in 可迭代对象)

生成器表达式返回生成器对象,惰性求值,节省内存。

# 生成器表达式
g = (x * x for x in range(5))
print(type(g))  # <class 'generator'>

# 使用 next() 获取下一个值
print(next(g))  # 0
print(next(g))  # 1

# 转换为列表
squares = list(g)
print(squares)  # [4, 9, 16](注意:前面已经消耗了 0 和 1)

# 直接遍历
g = (x * x for x in range(5))
for square in g:
    print(square)  # 0, 1, 4, 9, 16

# 内存优势:处理大量数据
# 列表推导式(占用内存)
big_list = [x * x for x in range(1000000)]  # 创建完整列表

# 生成器表达式(节省内存)
big_gen = (x * x for x in range(1000000))  # 不创建列表,按需生成

10.5 推导式 vs 传统循环

性能对比

# 列表推导式通常更快
import time

# 方法 1:列表推导式
start = time.time()
result1 = [x * x for x in range(1000000)]
time1 = time.time() - start

# 方法 2:传统循环
start = time.time()
result2 = []
for x in range(1000000):
    result2.append(x * x)
time2 = time.time() - start

print(f"列表推导式: {time1:.4f}秒")
print(f"传统循环: {time2:.4f}秒")
# 列表推导式通常更快

可读性

  • 简单情况:推导式更简洁
  • 复杂逻辑:传统循环更清晰

10.6 练习题

练习 10.1:列表推导式 使用列表推导式完成以下任务:

  1. 生成 1-20 之间所有偶数的平方
  2. 从字符串列表 ["apple", "banana", "cherry"] 中提取长度大于 5 的字符串
  3. 将两个列表 [1, 2, 3][4, 5, 6] 组合成元组列表
查看答案
# 1. 偶数的平方
even_squares = [x * x for x in range(1, 21) if x % 2 == 0]
print(even_squares)  # [4, 16, 36, 64, 100, 144, 196, 256, 324, 400]

# 2. 长度大于 5 的字符串
fruits = ["apple", "banana", "cherry"]
long_fruits = [fruit for fruit in fruits if len(fruit) > 5]
print(long_fruits)  # ['banana', 'cherry']

# 3. 组合成元组列表
list1 = [1, 2, 3]
list2 = [4, 5, 6]
combined = [(x, y) for x in list1 for y in list2]
print(combined)  # [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

# 或使用 zip
combined = [(x, y) for x, y in zip(list1, list2)]
print(combined)  # [(1, 4), (2, 5), (3, 6)]

练习 10.2:字典推导式 使用字典推导式完成以下任务:

  1. 创建一个字典,键为 1-10,值为键的平方
  2. 从学生列表创建字典:[("Alice", 85), ("Bob", 90), ("Charlie", 78)],键为姓名,值为成绩
  3. 筛选出成绩大于 80 的学生
查看答案
# 1. 平方字典
squares = {x: x * x for x in range(1, 11)}
print(squares)  # {1: 1, 2: 4, 3: 9, ..., 10: 100}

# 2. 学生成绩字典
students = [("Alice", 85), ("Bob", 90), ("Charlie", 78)]
scores = {name: score for name, score in students}
print(scores)  # {'Alice': 85, 'Bob': 90, 'Charlie': 78}

# 3. 筛选成绩大于 80
high_scores = {name: score for name, score in students if score > 80}
print(high_scores)  # {'Alice': 85, 'Bob': 90}

练习 10.3:生成器表达式 使用生成器表达式计算 1-1000 所有数字的平方和,比较内存使用。

查看答案
# 使用生成器表达式(节省内存)
squares_gen = (x * x for x in range(1, 1001))
total = sum(squares_gen)
print(f"平方和: {total}")  # 333833500

# 对比:列表推导式(占用更多内存)
squares_list = [x * x for x in range(1, 1001)]
total = sum(squares_list)
print(f"平方和: {total}")  # 333833500

# 生成器表达式在处理大数据时更有优势

练习 10.4:综合练习 编写一个函数,接受一个字符串列表,返回一个字典,键为字符串,值为字符串中元音字母的数量。

查看答案
def count_vowels_in_words(words):
    """统计每个单词中元音字母的数量"""
    vowels = "aeiouAEIOU"
    return {word: sum(1 for char in word if char in vowels) for word in words}

words = ["hello", "world", "python", "programming"]
result = count_vowels_in_words(words)
print(result)  # {'hello': 2, 'world': 1, 'python': 1, 'programming': 3}

十一、迭代器 & 生成器函数(yield)

1. 简单生成器

def countdown(n):
    while n > 0:
        yield n
        n -= 1

for i in countdown(3):
    print(i)

yield 让函数变成生成器,可惰性输出,适合大数据流。


十二、lambda & 内置高阶函数(map/filter/sorted)

# 匿名函数
add = lambda x, y: x + y
add(2, 3)

# map
nums = [1, 2, 3]
res = list(map(lambda x: x * 2, nums))

# filter
evens = list(filter(lambda x: x % 2 == 0, nums))

# sorted + key
words = ["apple", "banana", "cat"]
sorted(words, key=len)  # 按长度排

十三、装饰器(decorator)

装饰器本质是:接收函数,返回新函数

1. 一个最简单的装饰器

def log(func):
    def wrapper(*args, **kwargs):
        print("调用函数:", func.__name__)
        result = func(*args, **kwargs)
        print("结束函数:", func.__name__)
        return result
    return wrapper

@log
def hello(name):
    print("Hello,", name)

hello("Tom")

常见用途:日志、权限校验、缓存(如 functools.lru_cache)。


十四、上下文管理器(with) & 文件操作

with open("data.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)
# 自动关闭文件

自定义上下文管理器:

class MyCtx:
    def __enter__(self):
        print("进入")
        return self
    def __exit__(self, exc_type, exc, tb):
        print("退出")

with MyCtx():
    print("处理中")

十五、类型注解(type hints)

语法不会影响运行,只是给 IDE / 静态检查工具看的,对大型项目很重要。

from typing import List, Dict, Optional

def add(x: int, y: int) -> int:
    return x + y

def get_user(name: str) -> Dict[str, str]:
    return {"name": name}

def find(name: str) -> Optional[str]:
    ...

十六、异步编程(async / await)——进阶

适合 I/O 密集,如网络请求、爬虫、聊天服务。

import asyncio

async def fetch(url):
    print("start", url)
    await asyncio.sleep(1)  # 模拟 I/O
    print("done", url)
    return f"content of {url}"

async def main():
    urls = ["a.com", "b.com", "c.com"]
    tasks = [fetch(u) for u in urls]
    results = await asyncio.gather(*tasks)
    print(results)

asyncio.run(main())

配合 aiohttp, httpx 等库可以做高并发爬虫、接口调用。


十七、常用内置函数 & 语法糖补充

  • len()sum()max()min()any()all()
  • enumerate():同时要索引和元素
  • zip():并行遍历两个列表
  • 解包 * / **
a = [1, 2, 3]
b = [4, 5, 6]
for i, j in zip(a, b):
    print(i, j)

def f(x, y, z):
    print(x, y, z)

args = [1, 2, 3]
f(*args)  # f(1,2,3)

kwargs = {"x": 1, "y": 2, "z": 3}
f(**kwargs)

最后给你一个“循序渐进练习路线”

你可以按这个顺序边看语法边写小脚本:

  1. 基础语法 + 容器:做一个“学生成绩管理”小程序(增删改查,用 list/dict)
  2. 函数 & 模块:把功能拆到 utils.py,写一些通用工具函数。
  3. 异常 & 文件 & with:做一个简单的日志系统,写入 log 文件。
  4. 类 & OOP:把“学生/课程”设计成类,管理对象列表。
  5. 推导式/装饰器/生成器:做一些数据处理小任务,比如读取 CSV → 过滤 → 统计。
  6. 类型注解:给所有函数加上类型标注,让 IDE/编辑器提示更智能。
  7. async/await(可选):写一个简单的异步爬虫或多接口并发请求 demo。 ;