# Python基础语法全面教程

如果你是一名初学者,想成为Python大佬,那么可以按照本教程,把下面代码一字不落地敲一遍,理解并成功运行,这一步骤虽然很耗时,但就像扎马步一样,是成为武林高手的基本功。当然,如果你并不是fresh man,那么可以跳转到后面的Python高级进阶,会更适合你。

# 1. Python简介与特点

# 1.1 Python是什么

Python是一种高级、解释型、通用的编程语言,由Guido van Rossum于1991年创建。它强调代码的可读性和简洁的语法(特别是使用空格缩进来定义代码块)。

# 1.2 Python的主要特点

  • 简单易学:语法清晰,代码可读性高
  • 解释型语言:不需要编译,直接运行
  • 面向对象:支持面向对象编程
  • 动态类型:变量类型在运行时确定
  • 丰富的标准库:提供大量内置模块和包
  • 跨平台:可在Windows、Linux、macOS等系统运行
  • 开源免费:Python及其大多数库都是开源的
  • 强大的社区支持:拥有活跃的开发者社区

# 1.3 Python的应用领域

  • Web开发(Django, Flask)
  • 数据科学和机器学习(NumPy, Pandas, Scikit-learn)
  • 自动化脚本和运维
  • 网络爬虫
  • 游戏开发
  • 桌面应用程序
  • 人工智能和深度学习

# 2. Python环境搭建

# 2.1 安装Python

# Windows系统

  1. 访问Python官网 (opens new window)
  2. 下载最新版本的Python安装包
  3. 运行安装程序,务必勾选"Add Python to PATH"
  4. 按照安装向导完成安装

# macOS系统

# 使用Homebrew安装
brew install python3

# 或者从官网下载安装包
1
2
3
4

# Linux系统

# Ubuntu/Debian
sudo apt update
sudo apt install python3 python3-pip

# CentOS/RHEL
sudo yum install python3 python3-pip
1
2
3
4
5
6

# 2.2 验证安装

python --version
# 或
python3 --version
1
2
3

# 2.3 开发工具介绍

# 2.3.1 IDLE

Python自带的集成开发环境,适合初学者。

# 2.3.2 PyCharm

JetBrains推出的专业Python IDE,提供社区版和专业版。

# 2.3.3 VS Code

微软的轻量级代码编辑器,通过插件支持Python开发。

# 2.3.4 Jupyter Notebook

基于Web的交互式计算环境,适合数据科学和教学。

# 2.3.5 其他工具

  • Spyder:科学计算IDE
  • Sublime Text:轻量级文本编辑器
  • Atom:GitHub开发的编辑器

# 3. 第一个Python程序

# 3.1 交互式模式

# 打开终端或命令提示符,输入python或python3
>>> print("Hello, Python!")
Hello, Python!
1
2
3

# 3.2 脚本模式

创建hello.py文件:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 第一个Python程序
print("Hello, Python!")
print("Python是一门强大的编程语言!")

# 计算并输出结果
result = 10 + 20 * 3
print(f"计算结果:{result}")
1
2
3
4
5
6
7
8
9
10

运行脚本:

python hello.py
# 或
python3 hello.py
1
2
3

# 4. 基础语法

# 4.1 注释

# 单行注释

"""
多行注释(文档字符串)
可以跨越多行
通常用于模块、函数、类的说明
"""

'''
这也是多行注释
使用三个单引号
'''

# 行内注释
x = 10  # 这是一个行内注释
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 4.2 行与缩进

Python使用缩进来表示代码块,这是Python最显著的语法特征之一。

# 正确的缩进
if True:
    print("Hello")  # 缩进4个空格
    print("World")
else:
    print("Else block")

# 错误的缩进(会导致IndentationError)
if True:
print("错误的缩进")  # 缺少缩进

# 可以使用空格或制表符,但不能混用
# PEP 8建议使用4个空格进行缩进
1
2
3
4
5
6
7
8
9
10
11
12
13

# 4.3 多行语句

# 4.3.1 使用反斜杠

# 长表达式换行
total = 10 + 20 + 30 + \
        40 + 50 + 60 + \
        70 + 80

# 长字符串换行
long_string = "这是一个非常长的字符串,\
为了可读性,我们可以将它分成多行,\
但实际上是同一行"
1
2
3
4
5
6
7
8
9

# 4.3.2 括号内的多行

# 括号内的内容可以自动换行
my_list = [
    1, 2, 3,
    4, 5, 6,
    7, 8, 9
]

# 函数调用
result = some_function(argument1, argument2,
                      argument3, argument4)

# 字典
my_dict = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4.4 引号与字符串

# 单引号
str1 = 'Hello, World!'

# 双引号
str2 = "Hello, World!"

# 三引号(多行字符串)
str3 = """这是一个
多行字符串
可以包含多行内容"""

str4 = '''这也是一个
多行字符串'''

# 转义字符
str5 = "他说:\"你好!\""
str6 = '路径:C:\\Users\\name'
str7 = "第一行\n第二行\t制表符"

# 原始字符串(忽略转义)
str8 = r"C:\Users\name\Documents"

# 格式化字符串(Python 3.6+)
name = "Alice"
age = 25
str9 = f"姓名:{name},年龄:{age}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 4.5 输入与输出

# 4.5.1 输出(print函数)

# 基本输出
print("Hello, World!")

# 输出多个值,默认用空格分隔
print("Hello", "World", "!")  # 输出:Hello World !

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

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

# 格式化输出
name = "Alice"
age = 25
print("姓名:%s,年龄:%d" % (name, age))  # 旧式格式化
print("姓名:{},年龄:{}".format(name, age))  # str.format()
print(f"姓名:{name},年龄:{age}")  # f-string(推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 4.5.2 输入(input函数)

# 基本输入
name = input("请输入您的姓名:")
print(f"您好,{name}!")

# 输入转换为特定类型
age = int(input("请输入您的年龄:"))
height = float(input("请输入您的身高(米):"))

# 处理多个输入
values = input("请输入多个值,用空格分隔:").split()
print(f"您输入的值:{values}")

# 列表推导式处理输入
numbers = [int(x) for x in input("请输入多个数字,用空格分隔:").split()]
print(f"数字列表:{numbers}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 5. 变量与数据类型

# 5.1 变量

# 变量命名规则
# 1. 只能包含字母、数字和下划线
# 2. 不能以数字开头
# 3. 不能是Python关键字
# 4. 区分大小写

# 合法的变量名
my_variable = 10
variable2 = 20
_private_var = 30
MAX_VALUE = 100  # 常量(约定俗成,实际可以修改)

# 不推荐的命名(但仍合法)
变量 = 10  # 使用中文,不推荐
a = 1  # 无意义的名字,不推荐

# 变量赋值
x = 10  # 简单赋值
y = x + 5  # 表达式赋值
z = y = x = 10  # 链式赋值
a, b = 10, 20  # 多元赋值(元组解包)

# 变量交换
a, b = 10, 20
a, b = b, a  # 交换a和b的值
print(f"a={a}, b={b}")  # 输出:a=20, b=10

# 删除变量
x = 10
del x
# print(x)  # 这会引发NameError
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 5.2 标准数据类型

# 5.2.1 数字(Numbers)

# 整数(int)
x = 10
y = -5
z = 0

# 大整数(Python自动处理)
big_num = 123456789012345678901234567890
print(big_num)  # Python支持任意大小的整数

# 不同进制的整数
binary = 0b1010  # 二进制,10
octal = 0o12  # 八进制,10
hexadecimal = 0xA  # 十六进制,10

# 浮点数(float)
f1 = 3.14
f2 = 2.0
f3 = 2.  # 等同于2.0
f4 = .5  # 等同于0.5
f5 = 1.23e-4  # 科学计数法,0.000123

# 复数(complex)
c1 = 3 + 4j
c2 = complex(3, 4)  # 等同于3+4j
print(c1.real)  # 实部:3.0
print(c1.imag)  # 虚部:4.0
print(c1.conjugate())  # 共轭复数:3-4j

# 布尔值(bool)是int的子类
b_true = True   # 实际上是1
b_false = False  # 实际上是0
print(True + 1)  # 输出:2
print(False * 5)  # 输出:0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 5.2.2 字符串(String)

# 字符串创建
str1 = "Hello"
str2 = 'World'
str3 = """多行
字符串"""

# 字符串索引和切片
s = "Python"
print(s[0])     # 'P',第一个字符
print(s[-1])    # 'n',最后一个字符
print(s[0:3])   # 'Pyt',切片,包含开始,不包含结束
print(s[:3])    # 'Pyt',从头开始
print(s[3:])    # 'hon',到末尾结束
print(s[::2])   # 'Pto',步长为2
print(s[::-1])  # 'nohtyP',反转字符串

# 字符串常用方法
s = "  Hello, World!  "
print(s.lower())        # 转小写
print(s.upper())        # 转大写
print(s.strip())        # 去除两端空格
print(s.replace("World", "Python"))  # 替换
print(s.split(","))     # 分割,返回列表
print("Hello" + " " + "World")  # 字符串连接
print("Hello" * 3)      # 重复字符串

# 字符串查找
s = "Hello, World!"
print(s.find("World"))  # 返回索引,未找到返回-1
print(s.index("World")) # 返回索引,未找到引发异常
print("World" in s)     # 成员测试,返回布尔值

# 字符串格式化
name = "Alice"
age = 25
# 1. 旧式格式化
print("姓名:%s,年龄:%d" % (name, age))
# 2. str.format()
print("姓名:{},年龄:{}".format(name, age))
print("姓名:{0},年龄:{1}".format(name, age))
print("姓名:{name},年龄:{age}".format(name=name, age=age))
# 3. f-string(Python 3.6+,推荐)
print(f"姓名:{name},年龄:{age}")
print(f"明年年龄:{age + 1}")
print(f"姓名大写:{name.upper()}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 5.2.3 列表(List)

Python 中 list 的底层实现是动态数组(Dynamic Array),当向 list 中添加元素(如 append()、extend())时,如果 ob_size >= allocated,就会触发扩容:

  • 扩容策略:新容量 = 旧容量 + (旧容量>> 3) + (3 if 旧容量 < 9 else 6)。大致相当于每次扩容为原容量的 1.125 倍(小容量时额外增加一些空间)。
  • 扩容过程:分配新的内存空间,将原指针数组的内容复制到新空间,然后释放旧空间。

这种设计确保了append()操作的平均时间复杂度为 O (1)(虽然偶尔扩容会耗时O(n),但均摊后仍为常数级)。

# 列表创建
list1 = []  # 空列表
list2 = [1, 2, 3, 4, 5]
list3 = ["apple", "banana", "cherry"]
list4 = [1, "hello", 3.14, True]  # 可以包含不同类型
list5 = list("hello")  # 从可迭代对象创建。调用 list("hello") 时,list() 会遍历字符串 "hello",依次取出每个字,执行后,list5 的值为['h', 'e', 'l', 'l', 'o']
list6 = list(range(5))  # [0, 1, 2, 3, 4]
list7 = [i*2 for i in range(5)]  # 列表推导式:[0, 2, 4, 6, 8]

# 列表索引和切片(与字符串类似)
lst = [10, 20, 30, 40, 50]
print(lst[0])     # 10
print(lst[-1])    # 50
print(lst[1:3])   # [20, 30]
print(lst[:3])    # [10, 20, 30]
print(lst[2:])    # [30, 40, 50]
print(lst[::2])   # [10, 30, 50]
print(lst[::-1])  # [50, 40, 30, 20, 10]

# 列表常用方法
lst = [1, 2, 3]

# 添加元素
lst.append(4)          # [1, 2, 3, 4]
lst.extend([5, 6])     # [1, 2, 3, 4, 5, 6]
lst.insert(2, 2.5)     # [1, 2, 2.5, 3, 4, 5, 6]
# 删除元素
lst.remove(2.5)        # 删除第一个匹配项:[1, 2, 3, 4, 5, 6]
popped = lst.pop()     # 删除并返回最后一个元素:6
popped2 = lst.pop(1)   # 删除并返回索引1的元素:2
del lst[0]             # 删除索引0的元素
lst.clear()            # 清空列表

# 查找和统计
lst = [1, 2, 3, 2, 4, 2]
print(lst.index(2))    # 返回第一个匹配项的索引:1
print(lst.count(2))    # 统计出现次数:3
print(3 in lst)        # 成员测试:True

# 排序和反转
lst = [3, 1, 4, 1, 5, 9]
lst.sort()             # 原地排序:[1, 1, 3, 4, 5, 9]
lst.sort(reverse=True) # 降序排序:[9, 5, 4, 3, 1, 1]
lst.reverse()          # 反转列表

# 列表复制
lst1 = [1, 2, 3]
lst2 = lst1            # 引用,不是复制!
lst3 = lst1.copy()     # 浅复制
lst4 = lst1[:]         # 切片复制,也是浅复制

# 列表运算
lst1 = [1, 2, 3]
lst2 = [4, 5, 6]
print(lst1 + lst2)     # 连接:[1, 2, 3, 4, 5, 6]
print(lst1 * 3)        # 重复:[1, 2, 3, 1, 2, 3, 1, 2, 3]

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

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

for index, fruit in enumerate(fruits, start=1):
    print(f"{index}. {fruit}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# 5.2.4 元组(Tuple)

Python 中 tuple(元组)的底层实现与 list 非常相似,核心都是数组,但由于元组的不可变特性,底层设计更简洁。

# 元组创建
tuple1 = ()  # 空元组
# 在 Python 中,如果你定义tuple2 = (1),它不会被识别为元组,而是会被当作一个普通的整数。圆括号()本身不是元组的决定性标志,逗号 , 才是。
tuple2 = (1,)  # 单个元素的元组,注意逗号
tuple3 = (1, 2, 3)
tuple4 = 1, 2, 3  # 括号可以省略
tuple5 = tuple([1, 2, 3])  # 从列表转换

# 元组是不可变的
t = (1, 2, 3)
# t[0] = 10  # 错误!元组不可变

# 元组索引和切片(与列表相同)
t = (10, 20, 30, 40, 50)
print(t[0])     # 10
print(t[-1])    # 50
print(t[1:3])   # (20, 30)

# 元组拆包(解包)
t = (1, 2, 3)
a, b, c = t     # a=1, b=2, c=3

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

# 元组常用操作
t1 = (1, 2, 3)
t2 = (4, 5, 6)
print(t1 + t2)  # 连接:(1, 2, 3, 4, 5, 6)
print(t1 * 2)   # 重复:(1, 2, 3, 1, 2, 3)
print(2 in t1)  # 成员测试:True
print(len(t1))  # 长度:3

# 元组与列表的转换
lst = [1, 2, 3]
t = tuple(lst)  # 列表转元组
lst2 = list(t)  # 元组转列表

# 命名元组(collections模块)
from collections import namedtuple
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)  # 10 20
print(p[0], p[1])  # 10 20
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 5.2.5 集合(Set)

Python中set集合的底层实现是 哈希表Hash Table,用于存储唯一的元素。

# 集合创建
set1 = set()  # 空集合,注意不是{}。dict1 = {} 为空字典
set2 = {1, 2, 3}
set3 = set([1, 2, 3, 2, 1])  # 从列表创建,去重:{1, 2, 3}
set4 = {x for x in range(5)}  # 集合推导式:{0, 1, 2, 3, 4}

# 集合特性
# 1. 无序
# 2. 元素唯一(自动去重)
# 3. 元素必须是不可变类型(数字、字符串、元组)

# 集合运算
A = {1, 2, 3, 4}
B = {3, 4, 5, 6}

# 并集
print(A | B)   # {1, 2, 3, 4, 5, 6}
print(A.union(B))  # 同上

# 交集
print(A & B)   # {3, 4}
print(A.intersection(B))  # 同上

# 差集
print(A - B)   # {1, 2}
print(A.difference(B))  # 同上

# 对称差集(只在其中一个集合中)
print(A ^ B)   # {1, 2, 5, 6}
print(A.symmetric_difference(B))  # 同上

# 子集和超集
C = {1, 2}
print(C <= A)  # True,C是A的子集
print(C < A)   # True,C是A的真子集
print(A >= C)  # True,A是C的超集
print(A > C)   # True,A是C的真超集

# 集合方法
s = {1, 2, 3}

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

# 删除元素
s.remove(6)    # 删除元素,不存在则引发KeyError
s.discard(7)   # 删除元素,不存在不报错
popped = s.pop()  # 随机删除并返回一个元素
s.clear()    # 清空集合

# 其他方法
print(len(s))      # 长度
print(2 in s)      # 成员测试
s2 = s.copy()      # 浅复制

# 冻结集合(不可变集合)
fs = frozenset([1, 2, 3])
# fs.add(4)  # 错误!frozenset不可变
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

# 5.2.6 字典(Dictionary)

字典(dict)是内置的核心数据结构,以键值对(key-value)形式存储数据,其中键必须唯一且为可哈希类型(如 int、str、tuple),值则支持任意 Python 对象;Python 3.7 及以上版本正式保留插入顺序,底层基于高效的哈希表实现,插入、删除、查找操作的平均时间复杂度为 O(1),是快速实现数据映射、成员查找的理想选择。

# 字典创建
dict1 = {}  # 空字典
dict2 = {"name": "Alice", "age": 25}
dict3 = dict(name="Bob", age=30)  # 使用dict()构造函数
dict4 = dict([("name", "Charlie"), ("age", 35)])  # 从键值对列表
dict5 = {x: x**2 for x in range(5)}  # 字典推导式:{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 访问字典元素
d = {"name": "Alice", "age": 25}
print(d["name"])      # Alice
# print(d["gender"])  # KeyError,键不存在
print(d.get("name"))  # Alice
print(d.get("gender"))  # None,键不存在返回None
print(d.get("gender", "unknown"))  # unknown,提供默认值

# 修改字典
d["age"] = 26        # 修改值
d["gender"] = "female"  # 添加新键值对
d.update({"city": "Beijing", "age": 27})  # 批量更新

# 删除元素
del d["city"]        # 删除键值对
age = d.pop("age")   # 删除并返回值
key, value = d.popitem()  # 删除并返回最后一个键值对(Python 3.7+)
# d.clear()          # 清空字典

# 字典方法
d = {"a": 1, "b": 2, "c": 3}

# 获取所有键、值、键值对
keys = d.keys()      # 键视图
values = d.values()  # 值视图
items = d.items()    # 键值对视图

# 遍历字典
for key in d:
    print(key, d[key])

for key, value in d.items():
    print(key, value)

# 字典合并(Python 3.9+)
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
d3 = d1 | d2  # 合并,后者的值覆盖前者:{"a": 1, "b": 3, "c": 4}
d1 |= d2      # 原地合并
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

# 5.3 数据类型转换

# 隐式类型转换(自动)
x = 10      # int
y = 3.14    # float
z = x + y   # float,int自动转为float

# 显式类型转换(强制)
# 转换为整数
print(int(3.14))      # 3(向下取整)
print(int("10"))      # 10
print(int("1010", 2)) # 10(二进制字符串转整数)
# print(int("hello")) # ValueError

# 转换为浮点数
print(float(10))      # 10.0
print(float("3.14"))  # 3.14
print(float("inf"))   # inf(无穷大)
print(float("nan"))   # nan(非数字)

# 转换为字符串
print(str(10))        # "10"
print(str(3.14))      # "3.14"
print(str([1, 2, 3])) # "[1, 2, 3]"

# 转换为列表
print(list("hello"))          # ['h', 'e', 'l', 'l', 'o']
print(list((1, 2, 3)))        # [1, 2, 3]
print(list({1, 2, 3}))        # [1, 2, 3](顺序可能不同)
print(list({"a": 1, "b": 2})) # ['a', 'b'](只获取键)

# 转换为元组
print(tuple([1, 2, 3]))       # (1, 2, 3)
print(tuple("hello"))         # ('h', 'e', 'l', 'l', 'o')

# 转换为集合
print(set([1, 2, 2, 3, 3]))   # {1, 2, 3}
print(set("hello"))           # {'h', 'e', 'l', 'o'}(去重)

# 转换为字典(需要特定格式)
print(dict([("a", 1), ("b", 2)]))  # {'a': 1, 'b': 2}
print(dict(a=1, b=2))              # {'a': 1, 'b': 2}

# 转换为布尔值
print(bool(0))        # False
print(bool(1))        # True
print(bool(""))       # False(空字符串)
print(bool("hello"))  # True(非空字符串)
print(bool([]))       # False(空列表)
print(bool([1, 2]))   # True(非空列表)
print(bool(None))     # False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 6. 运算符

# 6.1 算术运算符

a = 10
b = 3

print(a + b)    # 加法:13
print(a - b)    # 减法:7
print(a * b)    # 乘法:30
print(a / b)    # 除法:3.333...(浮点数)
print(a // b)   # 整除:3(向下取整)
print(a % b)    # 取模:1
print(a ** b)   # 幂运算:1000
print(-a)       # 取负:-10
print(+a)       # 取正:10

# 增强赋值运算符
a += b    # 等同于 a = a + b
a -= b    # 等同于 a = a - b
a *= b    # 等同于 a = a * b
a /= b    # 等同于 a = a / b
a //= b   # 等同于 a = a // b
a %= b    # 等同于 a = a % b
a **= b   # 等同于 a = a ** b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 6.2 比较(关系)运算符

a = 10
b = 20

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

# 链式比较
x = 5
print(1 < x < 10)    # True
print(1 < x < 3)     # False
print(1 < x <= 5)    # True

# 字符串比较(按字典顺序)
print("apple" < "banana")  # True
print("apple" == "apple")  # True
print("apple" != "Apple")  # True(区分大小写)

# 列表比较(按元素顺序比较)
print([1, 2, 3] < [1, 2, 4])  # True
print([1, 2, 3] == [1, 2, 3]) # True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 6.3 赋值运算符

# 基本赋值
x = 10

# 多元赋值
x, y = 10, 20
x, y = y, x  # 交换x和y的值

# 链式赋值
a = b = c = 0

# 增强赋值
x = 10
x += 5   # x = x + 5
x -= 3   # x = x - 3
x *= 2   # x = x * 2
x /= 4   # x = x / 4
x //= 2  # x = x // 2
x %= 3   # x = x % 3
x **= 2  # x = x ** 2

# 位运算赋值
x = 5    # 二进制:0101
x &= 3   # 0011,结果:0001 (1)
x |= 2   # 0010,结果:0011 (3)
x ^= 5   # 0101,结果:0110 (6)
x <<= 1  # 左移1位:1100 (12)
x >>= 2  # 右移2位:0011 (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 6.4 逻辑运算符

# 逻辑与:and
print(True and True)    # True
print(True and False)   # False
print(False and True)   # False
print(False and False)  # False

# 逻辑或:or
print(True or True)     # True
print(True or False)    # True
print(False or True)    # True
print(False or False)   # False

# 逻辑非:not
print(not True)         # False
print(not False)        # True

# 短路求值
def func():
    print("函数被调用")
    return True

print(False and func())  # False,func()不会被调用
print(True or func())    # True,func()不会被调用

# 实际应用
x = 10
# 检查x是否在5到15之间
if x > 5 and x < 15:
    print("x在5到15之间")

# 检查x是否小于0或大于100
if x < 0 or x > 100:
    print("x超出范围")

# 非空检查
name = ""
if not name:
    print("姓名为空")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 6.5 位运算符

a = 10  # 二进制:1010
b = 4   # 二进制:0100

print(a & b)   # 按位与:0000 (0)
print(a | b)   # 按位或:1110 (14)
print(a ^ b)   # 按位异或:1110 (14)
print(~a)      # 按位取反:-(a+1) = -11
print(a << 1)  # 左移1位:10100 (20)
print(a >> 1)  # 右移1位:0101 (5)

# 应用:检查奇偶性
x = 7
if x & 1:  # 与1进行按位与
    print("奇数")
else:
    print("偶数")

# 应用:快速乘除2的幂次
x = 10
print(x << 1)  # 乘以2:20
print(x << 2)  # 乘以4:40
print(x >> 1)  # 除以2:5
print(x >> 2)  # 除以4:2(整数除法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 6.6 成员运算符

# in:如果在序列中找到值返回True
# not in:如果在序列中没有找到值返回True

lst = [1, 2, 3, 4, 5]
print(3 in lst)      # True
print(10 in lst)     # False
print(10 not in lst) # True

string = "Hello, World!"
print("Hello" in string)   # True
print("Python" in string)  # False

d = {"a": 1, "b": 2}
print("a" in d)      # True(检查键)
print(1 in d)        # False(不检查值)
print(1 in d.values())  # True(检查值)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 6.7 身份运算符

# is:判断两个对象是否是同一个对象(内存地址相同)
# is not:判断两个对象是否不是同一个对象

a = [1, 2, 3]
b = a      # b引用a
c = [1, 2, 3]  # 创建新列表

print(a is b)      # True,同一对象
print(a is c)      # False,不同对象
print(a == c)      # True,值相同
print(a is not c)  # True

# 小整数对象池(Python优化)
x = 10
y = 10
print(x is y)  # True,Python缓存小整数

# 字符串驻留
s1 = "hello"
s2 = "hello"
print(s1 is s2)  # True,Python会驻留字符串

# None比较
x = None
print(x is None)     # True
print(x is not None) # False
print(x == None)     # True(但不推荐,使用is)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 6.8 运算符优先级

"""
运算符优先级(从高到低):
1. **                     # 指数
2. ~ + -                 # 按位翻转,一元加号和减号
3. * / % //              # 乘,除,取模,整除
4. + -                   # 加法,减法
5. << >>                 # 左移,右移
6. &                     # 按位与
7. ^ |                   # 按位异或,按位或
8. <= < > >=             # 比较运算符
9. == !=                 # 等于运算符
10. = %= /= //= -= += *= **=  # 赋值运算符
11. is is not            # 身份运算符
12. in not in            # 成员运算符
13. not or and           # 逻辑运算符(not > and > or)
"""

# 示例
result = 2 + 3 * 4  # 14,乘法优先级高于加法
result = (2 + 3) * 4  # 20,括号改变优先级

# 逻辑运算符优先级:not > and > or
print(True or False and False)  # True,相当于True or (False and False)
print(not True and False)       # False,相当于(not True) and False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 7. 流程控制

# 7.1 条件控制(if语句)

# 基本if语句
x = 10
if x > 0:
    print("x是正数")

# if-else语句
x = -5
if x > 0:
    print("x是正数")
else:
    print("x是非正数")

# if-elif-else语句
score = 85
if score >= 90:
    print("优秀")
elif score >= 80:
    print("良好")
elif score >= 60:
    print("及格")
else:
    print("不及格")

# 嵌套if语句
x = 15
if x > 0:
    if x % 2 == 0:
        print("正偶数")
    else:
        print("正奇数")
else:
    print("非正数")

# 条件表达式(三元运算符)
x = 10
result = "正数" if x > 0 else "非正数"
print(result)

# 多条件判断
x = 10
y = 20
if x > 0 and y > 0:
    print("x和y都是正数")

if x > 0 or y > 0:
    print("x或y是正数")

# 空值检查
name = ""
if not name:
    print("姓名为空")

# 检查列表是否为空
my_list = []
if my_list:
    print("列表不为空")
else:
    print("列表为空")

# 多值比较
x = 5
if 1 < x < 10:
    print("x在1和10之间")

# match-case语句(Python 3.10+)
def http_status(status):
    match status:
        case 200:
            return "OK"
        case 404:
            return "Not Found"
        case 500:
            return "Internal Server Error"
        case _:
            return "Unknown status"

print(http_status(200))  # OK
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# 7.2 循环语句

# 7.2.1 while循环

# 基本while循环
count = 0
while count < 5:
    print(f"count: {count}")
    count += 1

# while-else语句
count = 0
while count < 3:
    print(f"count: {count}")
    count += 1
else:
    print("循环正常结束")  # 当循环条件为False时执行

# 无限循环(通常配合break使用)
while True:
    user_input = input("请输入命令(输入quit退出): ")
    if user_input.lower() == "quit":
        break
    print(f"执行命令: {user_input}")

# 使用while循环遍历列表
fruits = ["apple", "banana", "cherry"]
index = 0
while index < len(fruits):
    print(fruits[index])
    index += 1

# 求1到100的和
total = 0
n = 1
while n <= 100:
    total += n
    n += 1
print(f"1到100的和: {total}")

# 斐波那契数列
a, b = 0, 1
count = 0
while count < 10:
    print(a, end=" ")
    a, b = b, a + b
    count += 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 7.2.2 for循环

# 基本for循环
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
    print(fruit)

# 使用range()函数
for i in range(5):  # 0到4
    print(i)

for i in range(1, 6):  # 1到5
    print(i)

for i in range(0, 10, 2):  # 0到9,步长为2
    print(i)

for i in range(10, 0, -1):  # 10到1,倒序
    print(i)

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

# 遍历字典
person = {"name": "Alice", "age": 25, "city": "Beijing"}
for key in person:
    print(key, person[key])

for key, value in person.items():
    print(key, value)

for value in person.values():
    print(value)

# for-else语句
for i in range(5):
    print(i)
else:
    print("循环正常结束")  # 当循环完成时执行

# 嵌套循环
for i in range(3):
    for j in range(3):
        print(f"({i}, {j})", end=" ")
    print()  # 换行

# 列表推导式中的for循环
squares = [x**2 for x in range(10)]
print(squares)

# enumerate()获取索引和值
fruits = ["apple", "banana", "cherry"]
for index, fruit in enumerate(fruits):
    print(f"索引 {index}: {fruit}")

for index, fruit in enumerate(fruits, start=1):
    print(f"第{index}个水果: {fruit}")

# zip()同时遍历多个序列
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name} is {age} years old")

# 使用reversed()反向遍历
for i in reversed(range(5)):
    print(i)

# 使用sorted()排序遍历
numbers = [3, 1, 4, 1, 5, 9]
for num in sorted(numbers):
    print(num)

for num in sorted(set(numbers)):  # 去重后排序
    print(num)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# 7.2.3 break, continue, pass语句

# break语句:跳出当前循环
for i in range(10):
    if i == 5:
        break
    print(i)  # 输出:0 1 2 3 4

# continue语句:跳过当前迭代,继续下一次
for i in range(5):
    if i == 2:
        continue
    print(i)  # 输出:0 1 3 4

# pass语句:空语句,什么也不做,用作占位符
for i in range(5):
    if i == 2:
        pass  # 什么也不做,但语法需要
    print(i)  # 输出:0 1 2 3 4

# 实际应用
# 查找列表中的第一个负数
numbers = [3, 5, -1, 8, -4, 9]
first_negative = None
for num in numbers:
    if num < 0:
        first_negative = num
        break
print(f"第一个负数: {first_negative}")

# 跳过特定元素
numbers = [1, 2, 3, 4, 5, 6]
for num in numbers:
    if num % 2 == 0:  # 跳过偶数
        continue
    print(f"奇数: {num}")

# pass的典型用法:定义空函数或类
def empty_function():
    pass  # 以后实现

class EmptyClass:
    pass  # 以后实现

# 多层循环中的break
for i in range(3):
    for j in range(3):
        if i == 1 and j == 1:
            print("跳出内层循环")
            break  # 只跳出内层循环
        print(f"({i}, {j})")

# 使用标志跳出多层循环
found = False
for i in range(5):
    for j in range(5):
        if i == 2 and j == 2:
            found = True
            break
        print(f"({i}, {j})")
    if found:
        break

# 使用else子句处理循环未中断的情况
for i in range(5):
    if i == 10:  # 这个条件永远不会成立
        break
else:
    print("循环完成,没有遇到break")

# 搜索示例
numbers = [1, 3, 5, 7, 9]
search_for = 6
for num in numbers:
    if num == search_for:
        print(f"找到 {search_for}")
        break
else:
    print(f"未找到 {search_for}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# 8. 函数

# 8.1 函数定义与调用

# 函数定义
def greet():
    """这是一个简单的问候函数"""
    print("Hello, World!")

# 函数调用
greet()  # 输出: Hello, World!

# 带参数的函数
def greet_person(name):
    """向指定的人问候"""
    print(f"Hello, {name}!")

greet_person("Alice")  # 输出: Hello, Alice!
greet_person("Bob")    # 输出: Hello, Bob!

# 带返回值的函数
def add(a, b):
    """返回两个数的和"""
    return a + b

result = add(3, 5)
print(f"3 + 5 = {result}")  # 输出: 3 + 5 = 8

# 多个返回值, 返回类型为一个元组
def get_min_max(numbers):
    """返回列表中的最小值和最大值"""
    return min(numbers), max(numbers)

nums = [3, 1, 4, 1, 5, 9]
minimum, maximum = get_min_max(nums)
print(f"最小值: {minimum}, 最大值: {maximum}")

# 无返回值函数(返回None)
def print_list(lst):
    """打印列表的每个元素"""
    for item in lst:
        print(item)
    # 函数隐式返回None

result = print_list([1, 2, 3])
print(f"函数返回值: {result}")  # 输出: None
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 8.2 参数传递

# 8.2.1 位置参数

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

# 按位置传递参数
describe_pet('dog', 'willie')    # 正确
describe_pet('hamster', 'harry') # 正确
# describe_pet('willie', 'dog')  # 错误:参数顺序不对
1
2
3
4
5
6
7
8
9

# 8.2.2 关键字参数

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

# 使用关键字参数
describe_pet(animal_type='dog', pet_name='willie')
describe_pet(pet_name='willie', animal_type='dog')  # 顺序不重要

# 混合使用位置参数和关键字参数
describe_pet('dog', pet_name='willie')  # 正确
# describe_pet(animal_type='dog', 'willie')  # 错误:关键字参数必须在位置参数之后
1
2
3
4
5
6
7
8
9
10
11
12

# 8.2.3 默认参数

def describe_pet(pet_name, animal_type='dog'):
    """显示宠物的信息(animal_type有默认值)"""
    print(f"\nI have a {animal_type}.")
    print(f"My {animal_type}'s name is {pet_name.title()}.")

# 使用默认参数
describe_pet('willie')            # 使用默认的animal_type='dog'
describe_pet('harry', 'hamster')  # 覆盖默认值

# 默认参数的注意事项
def add_to_list(value, lst=[]):
    """向列表添加元素(有问题的默认参数)"""
    lst.append(value)
    return lst

print(add_to_list(1))  # [1]
print(add_to_list(2))  # [1, 2] 问题:默认列表被共享了!

# 正确的做法:使用None作为默认值
def add_to_list_fixed(value, lst=None):
    """向列表添加元素(正确的实现)"""
    if lst is None:
        lst = []
    lst.append(value)
    return lst

print(add_to_list_fixed(1))  # [1]
print(add_to_list_fixed(2))  # [2] 正确:每次都创建新列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 8.2.4 可变参数

# *args:接收任意数量的位置参数
def make_pizza(*toppings):
    """打印顾客点的所有配料"""
    print("\nMaking a pizza with the following toppings:")
    for topping in toppings:
        print(f"- {topping}")

make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')

# args是一个元组
def sum_numbers(*args):
    """计算所有参数的和"""
    print(f"args类型: {type(args)}")  # tuple
    return sum(args)

print(f"和: {sum_numbers(1, 2, 3, 4, 5)}")  # 15

# **kwargs:接收任意数量的关键字参数
def build_profile(first, last, **user_info):
    """创建一个包含用户信息的字典"""
    profile = {'first_name': first, 'last_name': last}
    profile.update(user_info)
    return profile

user_profile = build_profile('albert', 'einstein',
                             location='princeton',
                             field='physics')
print(user_profile)

# kwargs是一个字典
def print_kwargs(**kwargs):
    """打印所有关键字参数"""
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_kwargs(name='Alice', age=25, city='Beijing')

# 混合使用各种参数
def func(a, b, *args, c=10, d=20, **kwargs):
    """混合参数示例"""
    print(f"a: {a}, b: {b}")
    print(f"args: {args}")
    print(f"c: {c}, d: {d}")
    print(f"kwargs: {kwargs}")

func(1, 2, 3, 4, 5, c=30, e=40, f=50)
# 输出:
# a: 1, b: 2
# args: (3, 4, 5)
# c: 30, d: 20
# kwargs: {'e': 40, 'f': 50}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

# 8.2.5 参数解包

# 使用*解包列表/元组作为位置参数
def print_coordinates(x, y, z):
    print(f"坐标: ({x}, {y}, {z})")

point = [10, 20, 30]
print_coordinates(*point)  # 等同于 print_coordinates(10, 20, 30)

# 使用**解包字典作为关键字参数
def introduce(name, age, city):
    print(f"{name}, {age}岁, 来自{city}")

person = {'name': 'Alice', 'age': 25, 'city': 'Beijing'}
introduce(**person)  # 等同于 introduce(name='Alice', age=25, city='Beijing')

# 混合解包
def func(a, b, c, d):
    print(f"a={a}, b={b}, c={c}, d={d}")

args = [1, 2]
kwargs = {'c': 3, 'd': 4}
func(*args, **kwargs)  # 等同于 func(1, 2, c=3, d=4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 8.3 匿名函数(lambda)

# lambda函数:小型匿名函数
# 语法:lambda 参数: 表达式

# 简单的lambda函数
add = lambda x, y: x + y
print(add(3, 5))  # 8

# 与普通函数的对比
def add_function(x, y):
    return x + y

# lambda函数通常用于需要函数对象的地方
# 1. 作为参数传递给高阶函数
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x**2, numbers))
print(squares)  # [1, 4, 9, 16, 25]

# 2. 列表排序
students = [
    {'name': 'Alice', 'grade': 85},
    {'name': 'Bob', 'grade': 92},
    {'name': 'Charlie', 'grade': 78}
]

# 按成绩排序
students.sort(key=lambda student: student['grade'])
print(students)

# 按姓名排序
students.sort(key=lambda student: student['name'])
print(students)

# 3. 过滤列表
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers)  # [2, 4, 6, 8, 10]

# 4. 立即调用lambda函数
result = (lambda x, y: x * y)(3, 4)
print(result)  # 12

# 5. 在字典排序中使用
d = {'apple': 5, 'banana': 2, 'cherry': 8}
sorted_items = sorted(d.items(), key=lambda item: item[1])  # 按值排序
print(sorted_items)  # [('banana', 2), ('apple', 5), ('cherry', 8)]

# lambda的局限性:只能包含一个表达式
# 以下是非法的:
# lambda x: x = x + 1  # 不能包含赋值语句
# lambda x: if x > 0: return x else: return -x  # 不能包含条件语句

# 可以使用条件表达式
abs_value = lambda x: x if x >= 0 else -x
print(abs_value(-5))  # 5
print(abs_value(3))   # 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 8.4 变量作用域

# 局部变量
def func():
    local_var = "我是局部变量"
    print(local_var)  # 可以访问

func()
# print(local_var)  # 错误:局部变量不能在函数外访问

# 全局变量
global_var = "我是全局变量"

def func1():
    print(global_var)  # 可以访问全局变量

def func2():
    global_var = "我修改了全局变量吗?"  # 实际上创建了新的局部变量
    print(global_var)  # 输出局部变量

func1()  # 输出: 我是全局变量
func2()  # 输出: 我修改了全局变量吗?
print(global_var)  # 输出: 我是全局变量(未被修改)

# 使用global关键字修改全局变量
def func3():
    global global_var
    global_var = "我真的修改了全局变量"
    print(global_var)

func3()  # 输出: 我真的修改了全局变量
print(global_var)  # 输出: 我真的修改了全局变量

# 嵌套作用域
def outer():
    outer_var = "我是外部函数的变量"
    
    def inner():
        nonlocal outer_var  # 使用nonlocal关键字
        outer_var = "我修改了外部函数的变量"
        print(f"inner: {outer_var}")
    
    print(f"调用inner前: {outer_var}")
    inner()
    print(f"调用inner后: {outer_var}")

outer()

# 闭包
def make_multiplier(factor):
    """创建一个乘法器函数"""
    def multiplier(x):
        return x * factor
    return multiplier

times2 = make_multiplier(2)
times3 = make_multiplier(3)

print(times2(5))  # 10
print(times3(5))  # 15

# 作用域链:LEGB规则
# Local -> Enclosing -> Global -> Built-in
x = "global x"

def outer():
    x = "outer x"
    
    def inner():
        x = "inner x"
        print(x)  # 首先在局部作用域查找
    
    inner()
    print(x)  # 在outer的局部作用域查找

outer()
print(x)  # 在全局作用域查找

# 内置作用域
import builtins
print(dir(builtins))  # 查看所有内置名称

# 不要覆盖内置函数
# 错误示例:
str = "不要这样做!"  # 覆盖了内置的str()
# print(str(123))  # 错误:'str' object is not callable

# 恢复
del str
print(str(123))  # 正常:'123'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

# 8.5 函数高级特性

# 函数作为参数传递
def apply_function(func, value):
    """应用函数到值上"""
    return func(value)

def square(x):
    return x * x

def cube(x):
    return x * x * x

print(apply_function(square, 5))  # 25
print(apply_function(cube, 5))    # 125

# 函数作为返回值
def get_operation(operation_type):
    """根据操作类型返回相应的函数"""
    if operation_type == "square":
        return square
    elif operation_type == "cube":
        return cube
    else:
        return lambda x: x  # 返回恒等函数

operation = get_operation("square")
print(operation(4))  # 16

# 偏函数(functools.partial)
from functools import partial

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

# 创建平方函数
square = partial(power, exponent=2)
# 创建立方函数
cube = partial(power, exponent=3)

print(square(5))  # 25
print(cube(5))    # 125

# 生成器函数
def count_up_to(max):
    """生成从1到max的数字"""
    count = 1
    while count <= max:
        yield count
        count += 1

counter = count_up_to(5)
print(list(counter))  # [1, 2, 3, 4, 5]

# 递归函数
def factorial(n):
    """计算阶乘的递归函数"""
    if n <= 1:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))  # 120

# 尾递归优化(Python不支持尾递归优化,但可以这样写)
def factorial_tail(n, accumulator=1):
    """尾递归版本的阶乘函数"""
    if n <= 1:
        return accumulator
    else:
        return factorial_tail(n - 1, n * accumulator)

print(factorial_tail(5))  # 120
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

# 9. 模块与包

# 9.1 模块导入

# 9.1.1 基本导入

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

# 导入模块并指定别名
import numpy as np
np.array([1, 2, 3])

# 从模块导入特定函数/类
from math import sqrt, pi
print(sqrt(25))  # 5.0
print(pi)        # 3.141592653589793

# 导入模块中的所有内容(不推荐)
from math import *
print(sin(pi/2))  # 1.0

# 导入模块并指定别名(from...import...as...)
from math import sqrt as square_root
print(square_root(36))  # 6.0

# 相对导入(在包内部使用)
# from . import module_name  # 当前目录
# from .. import module_name # 上级目录
# from .subpackage import module_name  # 子包

# 动态导入
module_name = "math"
math_module = __import__(module_name)
print(math_module.sqrt(49))  # 7.0

# 使用importlib动态导入
import importlib
module = importlib.import_module("math")
print(module.sqrt(64))  # 8.0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 9.1.2 导入路径和搜索顺序

import sys

# 查看Python模块搜索路径
print("Python模块搜索路径:")
for path in sys.path:
    print(f"  {path}")

# 添加自定义路径到搜索路径
import os
custom_path = "/path/to/my/modules"
if custom_path not in sys.path:
    sys.path.append(custom_path)

# 查看已导入的模块
print("\n已导入的模块:")
for module_name in sorted(sys.modules.keys()):
    if not module_name.startswith('_'):
        print(f"  {module_name}")

# 重新加载模块
import importlib
import mymodule
# 修改mymodule.py后,重新加载
importlib.reload(mymodule)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 9.1.3 导入最佳实践

"""
导入顺序建议(PEP 8):
1. 标准库导入
2. 相关第三方库导入
3. 本地应用/库特定导入

每类导入之间用空行分隔
"""

# 好的导入示例
import os
import sys
from typing import Dict, List

import numpy as np
import pandas as pd

from mypackage import mymodule
from . import local_module

# 避免循环导入
"""
模块A导入模块B,模块B又导入模块A,会导致循环导入错误。
解决方案:
1. 重新组织代码结构
2. 将导入放在函数内部而不是模块顶部
3. 使用import语句而不是from...import
"""

# 条件导入
try:
    import optional_module
    OPTIONAL_AVAILABLE = True
except ImportError:
    OPTIONAL_AVAILABLE = False
    print("警告: optional_module不可用,使用降级功能")

if OPTIONAL_AVAILABLE:
    # 使用optional_module的功能
    result = optional_module.some_function()
else:
    # 降级方案
    result = fallback_function()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 9.2 常用内置模块介绍

# 9.2.1 math模块(数学运算)

import math

# 常数
print(f"π: {math.pi}")
print(f"自然常数e: {math.e}")
print(f"无穷大: {math.inf}")
print(f"非数字: {math.nan}")

# 基本运算
print(f"平方根: {math.sqrt(16)}")        # 4.0
print(f"幂运算: {math.pow(2, 3)}")       # 8.0
print(f"指数: {math.exp(1)}")           # e ≈ 2.718
print(f"自然对数: {math.log(10)}")       # ln(10)
print(f"以10为底对数: {math.log10(100)}") # 2.0

# 三角函数(参数为弧度)
angle_deg = 45
angle_rad = math.radians(angle_deg)  # 角度转弧度
print(f"sin({angle_deg}°): {math.sin(angle_rad)}")
print(f"cos({angle_deg}°): {math.cos(angle_rad)}")
print(f"tan({angle_deg}°): {math.tan(angle_rad)}")

# 反三角函数(返回弧度)
print(f"arcsin(0.5): {math.degrees(math.asin(0.5))}°")  # 30°

# 双曲函数
print(f"sinh(1): {math.sinh(1)}")
print(f"cosh(1): {math.cosh(1)}")

# 舍入函数
print(f"向下取整: {math.floor(3.7)}")   # 3
print(f"向上取整: {math.ceil(3.2)}")    # 4
print(f"截断取整: {math.trunc(3.7)}")   # 3
print(f"四舍五入: {round(3.14159, 2)}") # 3.14(注意:round是内置函数)

# 其他函数
print(f"绝对值: {math.fabs(-5)}")       # 5.0
print(f"阶乘: {math.factorial(5)}")     # 120
print(f"最大公约数: {math.gcd(12, 18)}") # 6
print(f"判断有限数: {math.isfinite(10)}") # True
print(f"判断无穷大: {math.isinf(math.inf)}") # True
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 9.2.2 random模块(随机数)

import random

# 设置随机种子(使结果可重复)
random.seed(42)

# 随机浮点数
print(f"[0,1)随机数: {random.random()}")
print(f"[a,b]随机数: {random.uniform(1, 10)}")

# 随机整数
print(f"[a,b]随机整数: {random.randint(1, 6)}")  # 模拟骰子
print(f"范围内随机整数: {random.randrange(0, 100, 5)}")  # 步长为5

# 序列操作
items = ['apple', 'banana', 'cherry', 'date']

# 随机选择
print(f"随机选择元素: {random.choice(items)}")
print(f"随机选择多个元素: {random.choices(items, k=2)}")

# 随机抽样(无放回)
print(f"随机抽样: {random.sample(items, 2)}")

# 打乱序列
shuffled = items.copy()
random.shuffle(shuffled)
print(f"打乱后: {shuffled}")

# 随机字节
print(f"随机字节: {random.randbytes(4)}")

# 概率分布
# 正态分布
print(f"正态分布: {random.normalvariate(0, 1)}")

# 指数分布
print(f"指数分布: {random.expovariate(1.0)}")

# 高斯分布(均值为0,标准差为1)
print(f"高斯分布: {random.gauss(0, 1)}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 9.2.3 datetime模块(日期时间)

import datetime

# 当前日期和时间
now = datetime.datetime.now()
print(f"当前时间: {now}")
print(f"日期部分: {now.date()}")
print(f"时间部分: {now.time()}")
print(f"年份: {now.year}")
print(f"月份: {now.month}")
print(f"日: {now.day}")
print(f"小时: {now.hour}")
print(f"分钟: {now.minute}")
print(f"秒: {now.second}")
print(f"微秒: {now.microsecond}")
print(f"星期几: {now.weekday()}")  # 0=周一, 6=周日
print(f"星期几(ISO): {now.isoweekday()}")  # 1=周一, 7=周日

# 创建特定日期时间
dt1 = datetime.datetime(2025, 12, 25, 10, 30, 45)
dt2 = datetime.datetime(2026, 1, 1, 0, 0, 0)

# 日期时间运算
delta = dt2 - dt1
print(f"时间差: {delta}")
print(f"天数: {delta.days}")
print(f"秒数: {delta.total_seconds()}")

# 时间增量
from datetime import timedelta
one_day = timedelta(days=1)
one_hour = timedelta(hours=1)
one_week = timedelta(weeks=1)

tomorrow = now + one_day
yesterday = now - one_day
print(f"明天: {tomorrow}")
print(f"昨天: {yesterday}")

# 日期格式化
print(f"ISO格式: {now.isoformat()}")
print(f"自定义格式: {now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"中文格式: {now.strftime('%Y年%m月%d日 %H时%M分%S秒')}")

# 字符串转日期时间
date_str = "2023-12-25 10:30:45"
dt = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')
print(f"解析结果: {dt}")

# 日期类(不含时间)
today = datetime.date.today()
print(f"今天: {today}")
birthday = datetime.date(1990, 5, 15)
print(f"生日: {birthday}")

# 时间类(不含日期)
current_time = datetime.time(14, 30, 45)
print(f"时间: {current_time}")

# 时区处理(需要pytz或zoneinfo模块)
from datetime import timezone

# 创建带时区的时间
utc_time = datetime.datetime.now(timezone.utc)
print(f"UTC时间: {utc_time}")

# 时区转换
from datetime import timedelta
beijing_time = utc_time + timedelta(hours=8)
print(f"北京时间: {beijing_time}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 9.2.4 os模块(操作系统接口)

import os

# 文件和目录操作
print(f"当前工作目录: {os.getcwd()}")

# 改变当前目录
os.chdir('/home/kelsen/Desktop')
print(f"新工作目录: {os.getcwd()}")

# 列出目录内容
print("目录内容:")
for item in os.listdir('.'):
    print(f"  {item}")

# 创建和删除目录
os.makedirs('test/subdir', exist_ok=True)  # 创建多层目录
os.rmdir('test/subdir')  # 删除空目录
#os.removedirs('test/subdir')  # 递归删除空目录

# 文件操作
# 检查文件/目录是否存在
print(f"文件是否存在: {os.path.exists('test.txt')}")

# 检查类型
print(f"是文件吗: {os.path.isfile('test.txt')}")
print(f"是目录吗: {os.path.isdir('.')}")

# 获取文件大小
if os.path.exists('test.txt'):
    size = os.path.getsize('test.txt')
    print(f"文件大小: {size}字节")

# 重命名文件
# os.rename('old.txt', 'new.txt')

# 删除文件
# os.remove('file.txt')

# 路径操作
file_path = '/home/kelsen/Desktop/file.txt'
print(f"目录名: {os.path.dirname(file_path)}")
print(f"文件名: {os.path.basename(file_path)}")
print(f"分割扩展名: {os.path.splitext(file_path)}")

# 拼接路径
full_path = os.path.join('/home', 'kelsen', 'Desktop', 'file.txt')
print(f"完整路径: {full_path}")

# 环境变量
print(f"PATH环境变量: {os.getenv('PATH', '未设置')}")

# 设置环境变量(当前进程)
os.environ['MY_VAR'] = 'my_value'
print(f"MY_VAR: {os.getenv('MY_VAR')}")

# 系统信息
print(f"操作系统: {os.name}")  # 'posix', 'nt', 'java'
print(f"行分隔符: {repr(os.linesep)}")
print(f"路径分隔符: {repr(os.pathsep)}")

# 执行系统命令
result = os.system('ls -la')
print(f"命令返回值: {result}")

# 获取命令输出(推荐使用subprocess模块)
import subprocess
output = subprocess.check_output(['ls', '-la'], text=True)
print(f"命令输出:\n{output}")

# 遍历目录树
for root, dirs, files in os.walk('.'):
    for file in files:
        if file.endswith('.py'):
            print(f"Python文件: {os.path.join(root, file)}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# 9.2.5 sys模块(系统相关功能)

import sys

# 命令行参数
print(f"脚本名称: {sys.argv[0]}")
print(f"参数列表: {sys.argv[1:]}")

# Python解释器信息
print(f"Python版本: {sys.version}")
print(f"版本信息: {sys.version_info}")
print(f"平台: {sys.platform}")
print(f"可执行文件路径: {sys.executable}")

# 模块搜索路径
print("模块搜索路径:")
for i, path in enumerate(sys.path, 1):
    print(f"  {i}. {path}")

# 添加自定义路径
new_path = "/path/to/my/modules"
if new_path not in sys.path:
    sys.path.append(new_path)

# 标准输入/输出/错误
sys.stdout.write("标准输出\n")
sys.stderr.write("标准错误\n")

# 读取输入
# data = sys.stdin.read()

# 退出程序
# sys.exit(0)  # 正常退出
# sys.exit(1)  # 异常退出

# 递归深度限制
print(f"递归深度限制: {sys.getrecursionlimit()}")
# sys.setrecursionlimit(3000)  # 设置新限制

# 引用计数
a = [1, 2, 3]
print(f"a的引用计数: {sys.getrefcount(a)}")

# 字节序
print(f"字节序: {sys.byteorder}")  # 'little' 或 'big'

# 最大整数值
print(f"最大整数值: {sys.maxsize}")

# 默认编码
print(f"默认编码: {sys.getdefaultencoding()}")
print(f"文件系统编码: {sys.getfilesystemencoding()}")

# 内存信息
print(f"引用追踪: {sys.getallocatedblocks()}")  # 已分配的内存块数

# 异常信息
try:
    1 / 0
except ZeroDivisionError:
    exc_type, exc_value, exc_traceback = sys.exc_info()
    print(f"异常类型: {exc_type}")
    print(f"异常值: {exc_value}")
    print(f"跟踪对象: {exc_traceback}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

# 9.3 包的概念与创建

# 9.3.1 包的基本概念

"""
包(Package)是包含多个模块的目录。
包必须包含一个特殊的文件:__init__.py

包结构示例:
mypackage/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
    ├── __init__.py
    └── module3.py
"""

# __init__.py文件的作用:
# 1. 标识目录为Python包
# 2. 初始化包级别的代码
# 3. 控制包的导入行为
# 4. 定义__all__列表,指定from package import *时导入的模块

# 包的导入方式
"""
import mypackage.module1
from mypackage import module1
from mypackage.module1 import some_function
from mypackage.subpackage import module3
from mypackage.subpackage.module3 import another_function
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 9.3.2 创建包

# 创建包的基本步骤:
# 1. 创建包目录
# 2. 创建__init__.py文件
# 3. 创建模块文件

# 示例:创建数学运算包
"""
math_pkg/
├── __init__.py
├── basic.py
├── advanced.py
└── stats.py
"""

# __init__.py 示例
"""
# math_pkg/__init__.py

# 包级别的文档字符串
\"\"\"数学运算包
提供基本和高级数学运算功能
\"\"\"

# 版本信息
__version__ = "1.0.0"
__author__ = "Kelsen Jing"

# 导入包中的关键功能,使它们可以直接从包中访问
from .basic import add, subtract, multiply, divide
from .advanced import sqrt, power, factorial
from .stats import mean, median, mode

# 定义__all__列表
__all__ = [
    'add', 'subtract', 'multiply', 'divide',
    'sqrt', 'power', 'factorial',
    'mean', 'median', 'mode'
]
"""

# basic.py 示例
"""
# math_pkg/basic.py

\"\"\"基本数学运算\"\"\"

def add(a, b):
    \"\"\"返回两个数的和\"\"\"
    return a + b

def subtract(a, b):
    \"\"\"返回两个数的差\"\"\"
    return a - b

def multiply(a, b):
    \"\"\"返回两个数的积\"\"\"
    return a * b

def divide(a, b):
    \"\"\"返回两个数的商\"\"\"
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b
"""

# 使用包
"""
import math_pkg

result = math_pkg.add(10, 5)
print(result)  # 15

# 或者
from math_pkg import multiply
result = multiply(4, 6)
print(result)  # 24
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# 9.3.3 命名空间包(Python 3.3+)

"""
命名空间包(Namespace Package):
- 没有__init__.py文件的目录
- 可以将包分布在多个位置
- 在Python 3.3+中引入
"""

# 命名空间包示例
"""
# 目录结构:
# /path1/myapp/utils/
# ├── math.py
# └── string.py
#
# /path2/myapp/utils/
# ├── date.py
# └── file.py

# 将两个路径都添加到sys.path
import sys
sys.path.extend(['/path1', '/path2'])

# 现在可以导入myapp.utils包中的所有模块
import myapp.utils.math
import myapp.utils.date
"""

# 检查包类型
import myapp.utils
print(f"是常规包: {hasattr(myapp.utils, '__file__')}")
print(f"是命名空间包: {myapp.utils.__spec__.origin == 'namespace'}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 9.3.4 包开发最佳实践

"""
包开发建议:

1. 包结构组织
   mypackage/
   ├── __init__.py
   ├── core.py           # 核心功能
   ├── utils.py          # 工具函数
   ├── constants.py      # 常量定义
   ├── exceptions.py     # 自定义异常
   ├── models/           # 数据模型
   │   ├── __init__.py
   │   └── user.py
   ├── api/              # API接口
   │   ├── __init__.py
   │   └── v1.py
   └── tests/            # 测试代码
       ├── __init__.py
       ├── test_core.py
       └── test_utils.py

2. __init__.py 应该:
   - 包含包文档字符串
   - 定义__version__
   - 定义__all__列表
   - 导入关键功能(可选)
   - 尽量简洁,避免复杂逻辑

3. 相对导入
   # 在包内部使用相对导入
   from . import module
   from .submodule import function
   from ..parent import something

4. 安装依赖
   # setup.py 或 pyproject.toml
   # requirements.txt

5. 包分发
   # 使用setuptools或poetry
   # 发布到PyPI
"""

# setup.py 示例
"""
from setuptools import setup, find_packages

setup(
    name="mypackage",
    version="1.0.0",
    author="Your Name",
    author_email="your.email@example.com",
    description="A brief description of your package",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/yourusername/mypackage",
    packages=find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.6",
    install_requires=[
        "requests>=2.25.0",
        "numpy>=1.19.0",
    ],
)
"""

# 包元数据示例
"""
# mypackage/__init__.py

\"\"\"
MyPackage - 一个强大的Python包

提供各种有用的功能,包括:
- 数据处理
- 网络请求
- 文件操作
\"\"\"

__version__ = "1.0.0"
__author__ = "Your Name"
__email__ = "your.email@example.com"
__license__ = "MIT"

# 导入关键功能
from .core import main_function
from .utils import helper_function

# 定义公开接口
__all__ = [
    'main_function',
    'helper_function',
]
"""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

# 10. 文件操作

# 10.1 打开文件

# 10.1.1 打开文件的模式

"""
文件打开模式:
r  : 只读模式(默认)
w  : 写入模式,会覆盖已有文件
x  : 独占创建模式,文件已存在则失败
a  : 追加模式,在文件末尾添加内容
b  : 二进制模式
t  : 文本模式(默认)
+  : 读写模式(更新模式)

常用组合:
rt : 读取文本文件(默认)
wt : 写入文本文件,覆盖
at : 追加文本文件
rb : 读取二进制文件
wb : 写入二进制文件,覆盖
r+ : 读写文本文件,从开头开始
w+ : 读写文本文件,覆盖
a+ : 读写文本文件,从末尾开始
"""

# 打开文件的基本语法
# file = open(filename, mode='r', encoding=None, errors=None, newline=None)

# 改变当前目录, 确保此目录下有下面几个要打开的文件存在
os.chdir('/usr/software/jupyter')
# 示例
# 读取文本文件
with open('example.txt', 'r', encoding='utf-8') as f:
    content = f.read()

# 写入文本文件
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write("Hello, World!\n")

# 追加文本文件
with open('log.txt', 'a', encoding='utf-8') as f:
    f.write("New log entry\n")

# 读取二进制文件
with open('image.jpg', 'rb') as f:
    binary_data = f.read()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 10.1.2 文件编码

# 常见的文本文件编码
encodings = [
    'utf-8',      # Unicode,最常用
    'utf-16',     # Unicode,双字节
    'utf-32',     # Unicode,四字节
    'ascii',      # ASCII,仅支持英文字符
    'latin-1',    # ISO-8859-1,西欧语言
    'gbk',        # 简体中文
    'gb2312',     # 简体中文
    'big5',       # 繁体中文
    'shift_jis',  # 日文
    'euc-kr',     # 韩文
]

# 自动检测编码
import chardet

def detect_encoding(file_path):
    with open(file_path, 'rb') as f:
        raw_data = f.read(10000)  # 读取前10000字节进行检测
        result = chardet.detect(raw_data)
        return result['encoding']

# 处理编码错误
try:
    with open('file.txt', 'r', encoding='utf-8') as f:
        content = f.read()
except UnicodeDecodeError:
    # 尝试其他编码
    try:
        with open('file.txt', 'r', encoding='latin-1') as f:
            content = f.read()
    except UnicodeDecodeError:
        print("无法解码文件")

# 使用errors参数处理编码问题
with open('file.txt', 'r', encoding='utf-8', errors='ignore') as f:
    # 忽略无法解码的字符
    content = f.read()

with open('file.txt', 'r', encoding='utf-8', errors='replace') as f:
    # 用替换字符(�)替换无法解码的字符
    content = f.read()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

# 10.2 读写文件

# 10.2.1 读取文件

# 读取整个文件
with open('example.txt', 'r', encoding='utf-8') as f:
    content = f.read()  # 读取整个文件内容
    print(content)

# 逐行读取
with open('example.txt', 'r', encoding='utf-8') as f:
    for line in f:  # 文件对象是可迭代的
        print(line.strip())  # strip()去除末尾的换行符

# 读取所有行到列表
with open('example.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()  # 返回包含所有行的列表
    for line in lines:
        print(line.strip())

# 读取指定字节数
with open('example.txt', 'r', encoding='utf-8') as f:
    first_100_chars = f.read(100)  # 读取前100个字符
    print(first_100_chars)

# 读取一行
with open('example.txt', 'r', encoding='utf-8') as f:
    first_line = f.readline()  # 读取第一行
    second_line = f.readline()  # 读取第二行
    print(f"第一行: {first_line.strip()}")
    print(f"第二行: {second_line.strip()}")

# 使用迭代器逐行读取(内存高效)
def read_large_file(file_path):
    """读取大文件,逐行处理"""
    with open(file_path, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            # 处理每一行
            processed_line = line.strip()
            yield line_num, processed_line

# 使用生成器
for line_num, line in read_large_file('large_file.txt'):
    print(f"第{line_num}行: {line}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 10.2.2 写入文件

# 写入字符串
with open('output.txt', 'w', encoding='utf-8') as f:
    f.write("Hello, World!\n")
    f.write("This is a test.\n")

# 写入多行
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines(lines)  # writelines接受字符串列表

# 追加内容
with open('output.txt', 'a', encoding='utf-8') as f:
    f.write("This is appended content.\n")

# 格式化写入
data = [
    ("Alice", 25, "Engineer"),
    ("Bob", 30, "Designer"),
    ("Charlie", 35, "Manager")
]

with open('employees.csv', 'w', encoding='utf-8') as f:
    # 写入表头
    f.write("Name,Age,Job\n")
    
    # 写入数据
    for name, age, job in data:
        f.write(f"{name},{age},{job}\n")

# 二进制写入
with open('binary.bin', 'wb') as f:
    # 写入字节
    f.write(b'\x00\x01\x02\x03')
    
    # 写入整数(需要转换为字节)
    f.write((42).to_bytes(4, byteorder='little'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 10.2.3 读写JSON文件

import json

# 数据
data = {
    "name": "Alice",
    "age": 25,
    "city": "Beijing",
    "skills": ["Python", "JavaScript", "SQL"],
    "is_employed": True,
    "salary": None
}

# 写入JSON文件
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=2)
    # ensure_ascii=False: 允许非ASCII字符
    # indent=2: 缩进,美化输出

# 读取JSON文件
with open('data.json', 'r', encoding='utf-8') as f:
    loaded_data = json.load(f)
    print(loaded_data)

# JSON字符串操作
# 对象转JSON字符串
json_str = json.dumps(data, indent=2)
print(json_str)

# JSON字符串转对象
parsed_data = json.loads(json_str)
print(parsed_data)

# 处理自定义对象
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def to_dict(self):
        return {"name": self.name, "age": self.age}
    
    @classmethod
    def from_dict(cls, data):
        return cls(data["name"], data["age"])

person = Person("Alice", 25)

# 自定义编码器
class PersonEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Person):
            return obj.to_dict()
        return super().default(obj)

# 使用自定义编码器
person_json = json.dumps(person, cls=PersonEncoder)
print(person_json)

# 解码自定义对象
def person_decoder(obj_dict):
    if "name" in obj_dict and "age" in obj_dict:
        return Person(obj_dict["name"], obj_dict["age"])
    return obj_dict

person_obj = json.loads(person_json, object_hook=person_decoder)
print(f"姓名: {person_obj.name}, 年龄: {person_obj.age}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 10.2.4 读写CSV文件

import csv

# 数据
data = [
    ["Name", "Age", "City"],
    ["Alice", "25", "Beijing"],
    ["Bob", "30", "Shanghai"],
    ["Charlie", "35", "Guangzhou"]
]

# 写入CSV文件
with open('people.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f)
    writer.writerows(data)  # 写入所有行

# 读取CSV文件
with open('people.csv', 'r', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# 使用DictReader和DictWriter(推荐)
# 写入CSV文件(字典格式)
data_dict = [
    {"Name": "Alice", "Age": 25, "City": "Beijing"},
    {"Name": "Bob", "Age": 30, "City": "Shanghai"},
    {"Name": "Charlie", "Age": 35, "City": "Guangzhou"}
]

with open('people_dict.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ["Name", "Age", "City"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    
    writer.writeheader()  # 写入表头
    writer.writerows(data_dict)  # 写入数据

# 读取CSV文件(字典格式)
with open('people_dict.csv', 'r', newline='', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['Name']} is {row['Age']} years old from {row['City']}")

# 处理不同分隔符的CSV文件
with open('people.tsv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f, delimiter='\t')  # 制表符分隔
    writer.writerows(data)

# 读取TSV文件
with open('people.tsv', 'r', newline='', encoding='utf-8') as f:
    reader = csv.reader(f, delimiter='\t')
    for row in reader:
        print(row)

# 处理引号
with open('quoted.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.writer(f, quoting=csv.QUOTE_ALL)  # 引用所有字段
    writer.writerows(data)

# 读取包含特殊字符的CSV
with open('quoted.csv', 'r', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 10.3 文件操作常用方法

# 10.3.1 文件指针操作

# 文件指针位置
with open('example.txt', 'r+', encoding='utf-8') as f:
    # 获取当前指针位置
    print(f"初始位置: {f.tell()}")
    
    # 读取前10个字符
    content = f.read(10)
    print(f"读取的内容: {content}")
    print(f"读取后位置: {f.tell()}")
    
    # 移动指针到文件开头
    f.seek(0)
    print(f"移动到开头后位置: {f.tell()}")
    
    # 移动到第5个字符
    f.seek(5)
    print(f"移动到位置5后: {f.tell()}")
    
    # 文本模式下模拟“从当前位置向前移动2个字符”
    current_pos = f.tell()  # 获取当前位置(5)
    f.seek(current_pos + 2)  # 以文件开头为基准移动到7
    print(f"从当前位置向前移动2后: {f.tell()}")
    
    # 文本模式下先获取文件总长度,再模拟“从文件末尾向前移动5个字符”
    f.seek(0, 2)  # 先移动到文件末尾(文本模式仅支持0基准的末尾偏移)
    end_pos = f.tell()  # 获取文件总字符数
    target_pos = max(0, end_pos - 5)  # 计算末尾向前5的位置(避免负数)
    f.seek(target_pos)
    print(f"从末尾向前移动5后: {f.tell()}")
    
    # 读取当前位置到末尾的内容
    remaining = f.read()
    print(f"剩余内容: {remaining}")

# 二进制文件的指针操作(原有逻辑无需修改,二进制模式支持完整seek操作)
with open('binary.bin', 'wb') as f:
    f.write(b'0123456789')

with open('binary.bin', 'rb') as f:
    # 移动到第5个字节
    f.seek(5)
    print(f"位置5的字节: {f.read(1)}")  # b'5'
    
    # 使用tell()和seek()组合
    current_pos = f.tell()
    f.seek(0)
    print(f"文件开头: {f.read(1)}")  # b'0'
    f.seek(current_pos)
    print(f"回到之前位置: {f.tell()}")  # 6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 10.3.2 文件属性和状态

import os
import time

filename = 'example.txt'

# 检查文件是否存在
if os.path.exists(filename):
    print(f"{filename} 存在")
    
    # 获取文件大小
    size = os.path.getsize(filename)
    print(f"文件大小: {size} 字节")
    
    # 获取文件状态
    stat_info = os.stat(filename)
    
    # 访问时间
    access_time = time.ctime(stat_info.st_atime)
    print(f"最后访问时间: {access_time}")
    
    # 修改时间
    modify_time = time.ctime(stat_info.st_mtime)
    print(f"最后修改时间: {modify_time}")
    
    # 创建时间(Windows)
    if hasattr(stat_info, 'st_ctime'):
        create_time = time.ctime(stat_info.st_ctime)
        print(f"创建时间: {create_time}")
    
    # 文件权限
    print(f"文件模式: {oct(stat_info.st_mode)}")
    
    # 是否是文件
    print(f"是文件: {os.path.isfile(filename)}")
    
    # 是否是目录
    print(f"是目录: {os.path.isdir(filename)}")
    
    # 获取绝对路径
    abs_path = os.path.abspath(filename)
    print(f"绝对路径: {abs_path}")
    
    # 获取目录名和文件名
    dir_name = os.path.dirname(abs_path)
    base_name = os.path.basename(abs_path)
    print(f"目录: {dir_name}")
    print(f"文件名: {base_name}")
    
    # 分割扩展名
    name_without_ext, ext = os.path.splitext(base_name)
    print(f"文件名(无扩展名): {name_without_ext}")
    print(f"扩展名: {ext}")
else:
    print(f"{filename} 不存在")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# 10.3.3 文件锁定

import os

# 按需导入系统特定模块(解决跨平台导入报错问题)
try:
    import fcntl  # Unix/Linux/Mac 系统
except ImportError:
    fcntl = None  # Windows 系统会导入失败,设为None

try:
    import msvcrt  # Windows 系统
except ImportError:
    msvcrt = None  # Unix/Linux/Mac 系统会导入失败,设为None

def lock_file_unix(file_path):
    """Unix系统文件锁定"""
    if fcntl is None:
        print("当前系统不支持Unix文件锁定方法")
        return
    
    f = open(file_path, 'a')
    try:
        # 获取排他锁(非阻塞)
        fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
        print("文件已锁定")
        
        # 执行需要文件锁定的操作
        f.write("写入内容\n")
        
    except BlockingIOError:
        print("文件已被其他进程锁定")
    finally:
        # 释放锁
        fcntl.flock(f, fcntl.LOCK_UN)
        print("文件锁已释放")
        f.close()

def lock_file_windows(file_path):
    """Windows系统文件锁定"""
    if msvcrt is None:
        print("当前系统不支持Windows文件锁定方法")
        return
    
    f = open(file_path, 'a')
    try:
        # 锁定文件(非阻塞,锁定1个字节)
        msvcrt.locking(f.fileno(), msvcrt.LK_NBLCK, 1)
        print("文件已锁定")
        
        # 执行需要文件锁定的操作
        f.write("写入内容\n")
        
    except IOError:
        print("文件已被其他进程锁定")
    finally:
        try:
            # 解锁文件
            msvcrt.locking(f.fileno(), msvcrt.LK_UNLCK, 1)
            print("文件锁已释放")
        except:
            pass  # 解锁失败不影响文件关闭
        f.close()

# 跨平台文件锁定(使用第三方库portalocker)
try:
    import portalocker
    
    def lock_file_cross_platform(file_path):
        """跨平台文件锁定(推荐)"""
        with open(file_path, 'a', encoding='utf-8') as f:
            try:
                # 获取排他锁(非阻塞)
                portalocker.lock(f, portalocker.LOCK_EX | portalocker.LOCK_NB)
                print("文件已锁定(跨平台方式)")
                
                # 执行需要文件锁定的操作
                f.write("写入内容\n")
                
            except portalocker.LockException:
                print("文件已被其他进程锁定(跨平台方式)")
            finally:
                # 释放锁(文件关闭时会自动释放,无需手动操作)
                pass
    
    # 使用跨平台方法示例
    lock_file_cross_platform('locked_file.txt')
    
except ImportError:
    print("portalocker库未安装,自动使用系统特定方法")
    
    # 根据操作系统选择锁定方法
    if os.name == 'posix':  # Unix/Linux/Mac 系统
        lock_file_unix('locked_file.txt')
    elif os.name == 'nt':   # Windows 系统
        lock_file_windows('locked_file.txt')
    else:
        print("未知操作系统,无法锁定文件")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# 10.4 上下文管理器(with语句)

# 10.4.1 with语句的工作原理

# with语句的基本语法
# with expression [as variable]:
#     with-block

# 文件操作是最常见的with语句应用
with open('file.txt', 'r') as f:
    content = f.read()
# 文件会自动关闭,即使发生异常

# 等价于传统的try-finally写法
f = open('file.txt', 'r')
try:
    content = f.read()
finally:
    f.close()

# with语句的优势:
# 1. 代码更简洁
# 2. 确保资源被正确释放
# 3. 异常安全

# 支持上下文管理器的对象
# - 文件对象
# - 线程锁(threading.Lock)
# - 数据库连接
# - 网络连接
# - 等等...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 10.4.2 自定义上下文管理器

# 自定义上下文管理器需要实现 __enter__ 和 __exit__ 方法
class FileHandler:
    """自定义文件处理上下文管理器"""
    def __init__(self, filename, mode='r', encoding='utf-8'):
        self.filename = filename
        self.mode = mode
        self.encoding = encoding
        self.file = None
    
    def __enter__(self):
        """进入上下文时调用,返回资源对象"""
        print(f"打开文件: {self.filename}")
        self.file = open(self.filename, self.mode, encoding=self.encoding)
        return self.file  # 作为with语句中as后的变量
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文时调用,处理异常和资源释放"""
        print(f"关闭文件: {self.filename}")
        if self.file:
            self.file.close()
        
        # 处理异常:
        # - 返回True:忽略异常
        # - 返回False:抛出异常
        if exc_type:
            print(f"捕获异常: {exc_type.__name__}: {exc_val}")
            # 返回True表示已处理异常,不会向外抛出
            # return True
        return False

# 使用自定义上下文管理器
with FileHandler('custom.txt', 'w') as f:
    f.write("自定义上下文管理器示例\n")
    # 故意触发异常测试
    # 1 / 0  # 取消注释测试异常处理

# 使用contextlib简化上下文管理器
from contextlib import contextmanager

@contextmanager
def file_manager(filename, mode='r', encoding='utf-8'):
    """使用装饰器创建上下文管理器"""
    try:
        print(f"打开文件: {filename}")
        file = open(filename, mode, encoding=encoding)
        yield file  # 返回资源,暂停执行直到with块结束
    finally:
        print(f"关闭文件: {filename}")
        file.close()

# 使用简化版上下文管理器
with file_manager('contextlib.txt', 'w') as f:
    f.write("contextlib创建的上下文管理器\n")

# 实用示例:计时上下文管理器
@contextmanager
def timer(name="操作"):
    """计时上下文管理器,统计代码块执行时间"""
    import time
    start = time.time()
    try:
        yield  # 执行with块中的代码
    finally:
        end = time.time()
        print(f"{name}耗时: {end - start:.4f}秒")

# 使用计时上下文管理器
with timer("文件写入"):
    with open('large_file.txt', 'w') as f:
        for i in range(10000):
            f.write(f"第{i}行内容\n")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

# 10.4.3 多个上下文管理器

# 同时使用多个上下文管理器(逗号分隔)
with open('input.txt', 'r') as infile, open('output.txt', 'w') as outfile:
    # 读取输入文件并写入输出文件
    content = infile.read()
    outfile.write(content)

# 嵌套写法(等价于上面的简写)
with open('input.txt', 'r') as infile:
    with open('output.txt', 'w') as outfile:
        content = infile.read()
        outfile.write(content)

# 结合不同类型的上下文管理器
import threading
import time

# 同时使用文件锁和文件操作
lock = threading.Lock()
with lock, open('thread_safe.txt', 'a') as f:
    # 多线程环境下安全写入
    f.write(f"线程{threading.current_thread().name}写入: {time.time()}\n")

# 自定义多个上下文管理器组合
@contextmanager
def database_connection(db_name):
    """模拟数据库连接"""
    print(f"连接数据库: {db_name}")
    conn = f"DBConnection({db_name})"
    try:
        yield conn
    finally:
        print(f"关闭数据库连接: {db_name}")

@contextmanager
def transaction(conn):
    """模拟数据库事务"""
    print("开始事务")
    try:
        yield
        print("提交事务")
    except Exception as e:
        print(f"回滚事务: {e}")
        raise

# 组合使用数据库连接和事务
with database_connection('mydb') as conn, transaction(conn):
    print("执行数据库操作")
    # 模拟事务失败
    # raise ValueError("数据验证失败")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 11. 异常处理

# 11.1 异常类型

"""
Python常见异常类型:
BaseException          # 所有异常的基类
├── Exception          # 常规异常的基类
│   ├── ArithmeticError # 算术错误
│   │   ├── ZeroDivisionError # 除零错误
│   │   ├── OverflowError     # 溢出错误
│   │   └── FloatingPointError # 浮点错误
│   ├── LookupError     # 查找错误
│   │   ├── IndexError      # 索引错误
│   │   └── KeyError        # 键错误
│   ├── AttributeError  # 属性错误
│   ├── NameError       # 名称错误(变量未定义)
│   ├── TypeError       # 类型错误
│   ├── ValueError      # 值错误
│   ├── FileNotFoundError # 文件未找到
│   ├── IOError         # I/O错误
│   ├── ImportError     # 导入错误
│   ├── SyntaxError     # 语法错误
│   ├── IndentationError # 缩进错误
│   └── RuntimeError    # 运行时错误
├── KeyboardInterrupt  # 键盘中断(Ctrl+C)
└── SystemExit         # 系统退出
"""

# 常见异常示例
try:
    # 除零错误
    1 / 0
except ZeroDivisionError as e:
    print(f"除零错误: {e}")

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

try:
    # 键错误
    d = {"a": 1, "b": 2}
    print(d["c"])
except KeyError as e:
    print(f"键错误: {e}")

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

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

try:
    # 文件未找到错误
    with open('nonexistent.txt', 'r') as f:
        pass
except FileNotFoundError as e:
    print(f"文件未找到: {e}")

try:
    # 名称错误
    print(undefined_variable)
except NameError as e:
    print(f"名称错误: {e}")

try:
    # 属性错误
    s = "hello"
    s.append("world")
except AttributeError as e:
    print(f"属性错误: {e}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

# 11.2 try-except语句

# 基本try-except结构
try:
    # 可能引发异常的代码
    result = 10 / int(input("请输入一个除数: "))
    print(f"结果: {result}")
except ZeroDivisionError:
    # 处理特定异常
    print("错误:除数不能为零!")
except ValueError:
    # 处理另一种特定异常
    print("错误:请输入有效的整数!")
except Exception as e:
    # 捕获所有其他异常
    print(f"发生未知错误: {e}")

# try-except-else结构
try:
    num = int(input("请输入一个数字: "))
except ValueError:
    print("输入的不是有效数字!")
else:
    # 仅当try块无异常时执行
    print(f"你输入的数字是: {num}")
    print(f"数字的平方是: {num**2}")

# try-except-finally结构
try:
    f = open('temp.txt', 'w')
    f.write("测试内容")
    # 故意触发错误
    # 1 / 0
except Exception as e:
    print(f"发生错误: {e}")
finally:
    # 无论是否发生异常,都会执行
    print("执行finally块")
    if 'f' in locals() and not f.closed:
        f.close()
        print("文件已关闭")

# 捕获多个异常
try:
    lst = [1, 2, 3]
    index = int(input("请输入索引: "))
    print(f"值: {lst[index]}")
except (IndexError, ValueError) as e:
    # 捕获多种异常,统一处理
    print(f"错误: {e}")

# 异常的层次结构(捕获基类异常)
try:
    # 各种可能的错误
    operations = [
        lambda: 1/0,
        lambda: [1,2,3][10],
        lambda: int("abc")
    ]
    choice = int(input("选择操作(1-3): ")) - 1
    operations[choice]()
except ArithmeticError:
    print("算术运算错误")
except LookupError:
    print("查找错误(索引/键)")
except ValueError:
    print("值错误")
except Exception as e:
    print(f"其他错误: {e}")

# 异常对象的详细信息
try:
    1 / 0
except ZeroDivisionError as e:
    print(f"异常类型: {type(e)}")
    print(f"异常参数: {e.args}")
    print(f"异常描述: {str(e)}")
    
    # 打印完整的异常栈跟踪
    import traceback
    traceback.print_exc()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

# 11.3 抛出异常(raise)

# 基本raise语句
def divide(a, b):
    if b == 0:
        # 抛出异常
        raise ZeroDivisionError("除数不能为零!")
    return a / b

try:
    print(divide(10, 0))
except ZeroDivisionError as e:
    print(f"捕获异常: {e}")

# 重新抛出异常
try:
    divide(10, 0)
except ZeroDivisionError as e:
    print(f"记录错误: {e}")
    # 重新抛出原异常
    raise  # 等同于 raise e

# 抛出带自定义参数的异常
def validate_age(age):
    if not isinstance(age, int):
        raise TypeError(f"年龄必须是整数,而不是{type(age).__name__}")
    if age < 0 or age > 150:
        raise ValueError(f"年龄{age}超出有效范围(0-150)")
    return age

try:
    validate_age(-5)
except (TypeError, ValueError) as e:
    print(f"年龄验证失败: {e}")

# 链式异常(Python 3+)
try:
    divide(10, 0)
except ZeroDivisionError as e:
    # 抛出新异常,并保留原始异常上下文
    raise RuntimeError("计算失败") from e

# 忽略异常上下文
try:
    divide(10, 0)
except ZeroDivisionError as e:
    # 使用from None忽略原始异常
    raise RuntimeError("计算失败") from None

# 条件抛出异常
def process_data(data):
    if not data:
        # 仅当条件满足时抛出
        raise ValueError("数据不能为空")
    print(f"处理{len(data)}条数据")

try:
    process_data([])
except ValueError as e:
    print(f"数据处理失败: {e}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

# 11.4 自定义异常

# 自定义异常类(继承自Exception)
class ValidationError(Exception):
    """数据验证异常基类"""
    pass

class InvalidEmailError(ValidationError):
    """邮箱格式无效异常"""
    def __init__(self, email, message="邮箱格式无效"):
        self.email = email
        self.message = message
        super().__init__(f"{message}: {email}")

class InvalidPhoneError(ValidationError):
    """手机号格式无效异常"""
    def __init__(self, phone, message="手机号格式无效"):
        self.phone = phone
        self.message = message
        super().__init__(f"{message}: {phone}")
    
    def __str__(self):
        # 自定义异常字符串表示
        return f"手机号验证失败: {self.phone} ({self.message})"

# 使用自定义异常
import re

def validate_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    if not re.match(pattern, email):
        raise InvalidEmailError(email)
    return email

def validate_phone(phone):
    pattern = r'^1[3-9]\d{9}$'
    if not re.match(pattern, phone):
        raise InvalidPhoneError(phone, "必须是11位手机号")
    return phone

# 捕获自定义异常
try:
    validate_email("invalid-email")
    validate_phone("123456")
except InvalidEmailError as e:
    print(f"邮箱错误: {e}")
    print(f"无效邮箱: {e.email}")
except InvalidPhoneError as e:
    print(f"手机号错误: {e}")
    print(f"无效手机号: {e.phone}")
except ValidationError as e:
    # 捕获所有验证异常
    print(f"数据验证错误: {e}")

# 自定义异常的层次结构
class APIError(Exception):
    """API调用异常基类"""
    def __init__(self, code, message):
        self.code = code
        self.message = message
        super().__init__(f"[{code}] {message}")

class AuthError(APIError):
    """认证相关异常"""
    def __init__(self, message="认证失败"):
        super().__init__(401, message)

class PermissionError(APIError):
    """权限相关异常"""
    def __init__(self, message="权限不足"):
        super().__init__(403, message)

class NotFoundError(APIError):
    """资源未找到异常"""
    def __init__(self, resource, id):
        super().__init__(404, f"{resource} (ID: {id}) 未找到")

# 使用API异常
try:
    # 模拟API调用失败
    raise NotFoundError("用户", 123)
except APIError as e:
    print(f"API错误: {e}")
    print(f"错误码: {e.code}")
    print(f"错误信息: {e.message}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

# 12. 面向对象编程

# 12.1 类与对象

# 类的定义
class Person:
    """人类的基本类"""
    
    # 类属性(所有实例共享)
    species = "Homo sapiens"
    count = 0  # 统计实例数量
    
    # 构造方法(初始化方法)
    def __init__(self, name, age):
        # 实例属性(每个实例独有)
        self.name = name
        self.age = age
        # 更新类属性
        Person.count += 1
    
    # 实例方法
    def introduce(self):
        """自我介绍"""
        return f"大家好,我是{self.name},今年{self.age}岁。"

# 创建对象(实例化)
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

# 访问实例属性
print(f"姓名: {person1.name}, 年龄: {person1.age}")
print(f"姓名: {person2.name}, 年龄: {person2.age}")

# 调用实例方法
print(person1.introduce())
print(person2.introduce())

# 访问类属性
print(f"物种: {Person.species}")
print(f"实例数量: {Person.count}")

# 动态添加属性
person1.gender = "female"
person2.gender = "male"
print(f"{person1.name}的性别: {person1.gender}")

# 检查属性是否存在
print(hasattr(person1, 'gender'))  # True
print(hasattr(person1, 'height'))  # False

# 获取和设置属性
setattr(person1, 'height', 165)
print(getattr(person1, 'height'))  # 165
# 获取不存在的属性时提供默认值
print(getattr(person1, 'weight', 50))  # 50

# 删除属性
del person1.height
# print(person1.height)  # AttributeError

# 查看对象的所有属性
print(f"person1的属性: {person1.__dict__}")
print(f"Person类的属性: {Person.__dict__}")

# 检查对象类型
print(isinstance(person1, Person))  # True
print(type(person1) is Person)      # True

# 类的文档字符串
print(Person.__doc__)  # 人类的基本类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

# 12.2 属性与方法

class Student:
    """学生类"""
    
    # 类属性
    school = "北京大学"
    
    def __init__(self, name, score):
        self.name = name
        # 私有属性(约定以单下划线开头)
        self._score = score
        # 严格私有属性(双下划线,会被名称改写)
        self.__secret = "我的小秘密"
    
    # 实例方法
    def get_score(self):
        """获取分数(访问器方法)"""
        return self._score
    
    def set_score(self, score):
        """设置分数(修改器方法),包含验证逻辑"""
        if 0 <= score <= 100:
            self._score = score
        else:
            raise ValueError("分数必须在0-100之间")
    
    # 类方法(使用@classmethod装饰器)
    @classmethod
    def change_school(cls, new_school):
        """修改学校名称(类方法操作类属性)"""
        cls.school = new_school
        return cls.school
    
    # 静态方法(使用@staticmethod装饰器)
    @staticmethod
    def is_valid_score(score):
        """判断分数是否有效(静态方法,无类/实例参数)"""
        return isinstance(score, (int, float)) and 0 <= score <= 100
    
    # 属性装饰器(将方法转为属性)
    @property
    def grade(self):
        """根据分数计算等级(只读属性)"""
        if self._score >= 90:
            return "A"
        elif self._score >= 80:
            return "B"
        elif self._score >= 60:
            return "C"
        else:
            return "D"
    
    @grade.setter
    def grade(self, grade):
        """通过等级设置分数(可写属性)"""
        grade_map = {"A": 95, "B": 85, "C": 70, "D": 50}
        if grade in grade_map:
            self._score = grade_map[grade]
        else:
            raise ValueError("无效的等级")

# 使用各种方法
stu = Student("Charlie", 85)

# 实例方法
print(f"分数: {stu.get_score()}")
stu.set_score(92)
print(f"修改后分数: {stu.get_score()}")

# 类方法
print(f"当前学校: {Student.school}")
Student.change_school("清华大学")
print(f"修改后学校: {Student.school}")

# 静态方法
print(f"分数85是否有效: {Student.is_valid_score(85)}")
print(f"分数105是否有效: {Student.is_valid_score(105)}")

# 属性装饰器
print(f"等级: {stu.grade}")  # 像访问属性一样调用方法
stu.grade = "A"  # 通过等级设置分数
print(f"设置等级A后的分数: {stu.get_score()}")

# 私有属性访问
print(stu._score)  # 单下划线属性仍可访问(只是约定)
# print(stu.__secret)  # 双下划线属性无法直接访问
print(stu._Student__secret)  # 名称改写后可访问(不推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86

# 12.3 继承

# 父类(基类)
class Animal:
    """动物基类"""
    
    def __init__(self, name):
        self.name = name
    
    def eat(self):
        """吃的行为"""
        return f"{self.name}正在吃东西。"
    
    def sleep(self):
        """睡的行为"""
        return f"{self.name}正在睡觉。"
    
    def make_sound(self):
        """发出声音(需要子类实现)"""
        raise NotImplementedError("子类必须实现make_sound方法")

# 单继承
class Dog(Animal):
    """狗类(继承自动物类)"""
    
    def __init__(self, name, breed):
        # 调用父类构造方法
        super().__init__(name)
        self.breed = breed  # 子类新增属性
    
    # 重写父类方法
    def make_sound(self):
        return f"{self.name}({self.breed})汪汪叫!"
    
    # 新增方法
    def fetch(self):
        """捡东西"""
        return f"{self.name}正在捡球。"

# 多继承
class Pet:
    """宠物类"""
    
    def __init__(self, owner):
        self.owner = owner
    
    def play(self):
        """玩耍"""
        return f"{self.owner}正在和宠物玩耍。"

# 继承多个父类
class PetDog(Dog, Pet):
    """宠物狗类(继承自Dog和Pet)"""
    
    def __init__(self, name, breed, owner):
        # 调用多个父类的构造方法
        Dog.__init__(self, name, breed)
        Pet.__init__(self, owner)
    
    # 组合父类行为
    def interact(self):
        """与主人互动"""
        return f"{self.make_sound()} {self.play()}"

# 多层继承
class Puppy(PetDog):
    """小狗类(继承自PetDog)"""
    
    def make_sound(self):
        # 调用父类的make_sound方法
        parent_sound = super().make_sound()
        return f"{parent_sound}(小声版)"
    
    def nap(self):
        """小睡(重写并扩展父类方法)"""
        return f"{super().sleep()}(小狗睡得更香)"

# 使用继承的类
dog = Dog("旺财", "金毛")
print(dog.eat())          # 继承的方法
print(dog.make_sound())   # 重写的方法

pet_dog = PetDog("来福", "哈士奇", "小明")
print(pet_dog.fetch())    # 来自Dog类
print(pet_dog.play())     # 来自Pet类
print(pet_dog.interact()) # 组合方法

puppy = Puppy("小白", "柯基", "小红")
print(puppy.make_sound()) # 多层继承的方法
print(puppy.nap())        # 扩展的父类方法

# 检查继承关系
print(issubclass(Dog, Animal))    # True
print(issubclass(PetDog, Animal)) # True
print(issubclass(PetDog, Pet))    # True
print(isinstance(puppy, Puppy))   # True
print(isinstance(puppy, PetDog))  # True
print(isinstance(puppy, Dog))     # True
print(isinstance(puppy, Animal))  # True

# 方法解析顺序(MRO)
print(Puppy.__mro__)
# 输出: (<class '__main__.Puppy'>, <class '__main__.PetDog'>, 
#        <class '__main__.Dog'>, <class '__main__.Animal'>, 
#        <class '__main__.Pet'>, <class 'object'>)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

# 12.4 多态

# 多态的核心:不同类的对象响应相同的方法调用,表现出不同行为

class Shape:
    """形状基类"""
    def area(self):
        """计算面积(需要子类实现)"""
        raise NotImplementedError
    
    def perimeter(self):
        """计算周长(需要子类实现)"""
        raise NotImplementedError

class Circle(Shape):
    """圆形"""
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        import math
        return math.pi * self.radius **2
    
    def perimeter(self):
        import math
        return 2 * math.pi * self.radius
    
    def __str__(self):
        return f"圆形(半径:{self.radius})"

class Rectangle(Shape):
    """矩形"""
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height
    
    def perimeter(self):
        return 2 * (self.width + self.height)
    
    def __str__(self):
        return f"矩形(宽:{self.width},高:{self.height})"

class Triangle(Shape):
    """三角形(海伦公式)"""
    def __init__(self, a, b, c):
        # 验证三边是否合法
        if a + b <= c or a + c <= b or b + c <= a:
            raise ValueError("无效的三角形边长")
        self.a = a
        self.b = b
        self.c = c
    
    def area(self):
        # 海伦公式
        s = (self.a + self.b + self.c) / 2
        return (s * (s - self.a) * (s - self.b) * (s - self.c))** 0.5
    
    def perimeter(self):
        return self.a + self.b + self.c
    
    def __str__(self):
        return f"三角形(边长:{self.a}, {self.b}, {self.c})"

# 多态的体现:统一的接口处理不同对象
def calculate_total_area(shapes):
    """计算多个形状的总面积(多态应用)"""
    total = 0
    for shape in shapes:
        # 无论shape是Circle/Rectangle/Triangle,都调用area()
        total += shape.area()
        print(f"{shape} 的面积:{shape.area():.2f}")
    return total

def print_shape_info(shape):
    """打印形状信息(多态应用)"""
    print(f"形状:{shape}")
    print(f"面积:{shape.area():.2f}")
    print(f"周长:{shape.perimeter():.2f}")
    print("-" * 20)

# 创建不同形状的对象
shapes = [
    Circle(5),
    Rectangle(4, 6),
    Triangle(3, 4, 5)
]

# 统一处理不同对象
total_area = calculate_total_area(shapes)
print(f"总面积:{total_area:.2f}")

# 分别处理每个对象
for shape in shapes:
    print_shape_info(shape)

# 动态类型的多态
def process_shape(shape):
    """处理任意形状对象,无需提前知道具体类型"""
    if isinstance(shape, Shape):
        print(f"处理{shape}")
        print(f"面积:{shape.area():.2f}")
    else:
        print(f"{shape}不是有效的形状")

# 传递不同类型的对象
process_shape(Circle(3))
process_shape("不是形状的字符串")

# 鸭子类型(Duck Typing):不关心类型,只关心行为
class Square:
    """正方形(未继承Shape,但有相同方法)"""
    def __init__(self, side):
        self.side = side
    
    def area(self):
        return self.side **2
    
    def perimeter(self):
        return 4 * self.side
    
    def __str__(self):
        return f"正方形(边长:{self.side})"

# 即使Square未继承Shape,也能正常使用
square = Square(4)
print_shape_info(square)  # 正常工作,体现鸭子类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

# 12.5 封装

class BankAccount:
    """银行账户类(封装示例)"""
    
    def __init__(self, account_number, balance=0):
        # 私有属性(名称改写)
        self.__account_number = account_number  # 账号(完全私有)
        self.__balance = balance                # 余额(完全私有)
        self.__transaction_history = []         # 交易记录(完全私有)
    
    # 公共方法(接口)- 访问器
    def get_account_number(self):
        """获取账号(脱敏显示)"""
        # 只显示后四位
        return "****" + self.__account_number[-4:]
    
    def get_balance(self):
        """获取余额"""
        return self.__balance
    
    def get_transaction_history(self):
        """获取交易记录(只读)"""
        # 返回副本,防止外部修改
        return list(self.__transaction_history)
    
    # 公共方法(接口)- 修改器
    def deposit(self, amount):
        """存款"""
        if amount <= 0:
            raise ValueError("存款金额必须大于0")
        self.__balance += amount
        self.__add_transaction(f"存款 +{amount}", self.__balance)
    
    def withdraw(self, amount):
        """取款"""
        if amount <= 0:
            raise ValueError("取款金额必须大于0")
        if amount > self.__balance:
            raise ValueError("余额不足")
        self.__balance -= amount
        self.__add_transaction(f"取款 -{amount}", self.__balance)
    
    # 私有方法(内部使用)
    def __add_transaction(self, description, balance):
        """添加交易记录(私有方法)"""
        import datetime
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.__transaction_history.append({
            "timestamp": timestamp,
            "description": description,
            "balance": balance
        })
    
    # 属性装饰器封装
    @property
    def account_info(self):
        """账户信息(只读属性)"""
        return {
            "account_number": self.get_account_number(),
            "balance": self.get_balance(),
            "transaction_count": len(self.__transaction_history)
        }

# 使用封装的类
account = BankAccount("1234567890123456", 1000)

# 通过公共接口访问
print(f"账号:{account.get_account_number()}")
print(f"余额:{account.get_balance()}")

# 执行操作
account.deposit(500)
account.withdraw(200)

# 查看信息
print(f"当前余额:{account.get_balance()}")
print(f"账户信息:{account.account_info}")

# 查看交易记录
history = account.get_transaction_history()
for transaction in history:
    print(f"{transaction['timestamp']} - {transaction['description']} - 余额:{transaction['balance']}")

# 尝试直接访问私有属性(失败)
# print(account.__balance)  # AttributeError
# print(account.__account_number)  # AttributeError

# 尝试修改私有属性(失败)
# account.__balance = 1000000  # 实际创建了新的公共属性
# print(account.__balance)  # 1000000(新属性)
# print(account.get_balance())  # 1300(真正的余额未变)

# 封装的好处:
# 1. 数据安全:防止外部随意修改关键数据
# 2. 接口稳定:即使内部实现变化,公共接口保持不变
# 3. 控制访问:可以在修改器中添加验证逻辑
# 4. 隐藏实现:用户只需关注接口,无需了解内部细节
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

# 12.6 特殊方法(魔术方法)

class Book:
    """书籍类(特殊方法示例)"""
    
    def __init__(self, title, author, pages):
        """构造方法:初始化对象"""
        self.title = title
        self.author = author
        self.pages = pages
    
    def __str__(self):
        """字符串表示(用户友好):print()/str()调用"""
        return f"'{self.title}' by {self.author}"
    
    def __repr__(self):
        """官方字符串表示:repr()调用,用于调试"""
        return f"Book('{self.title}', '{self.author}', {self.pages})"
    
    def __len__(self):
        """长度:len()调用"""
        return self.pages
    
    def __getitem__(self, index):
        """索引访问:obj[index]"""
        if index == 0:
            return self.title
        elif index == 1:
            return self.author
        elif index == 2:
            return self.pages
        else:
            raise IndexError("索引超出范围(0-2)")
    
    def __setitem__(self, index, value):
        """索引赋值:obj[index] = value"""
        if index == 0:
            self.title = value
        elif index == 1:
            self.author = value
        elif index == 2:
            self.pages = value
        else:
            raise IndexError("索引超出范围(0-2)")
    
    def __contains__(self, item):
        """成员测试:item in obj"""
        return item in [self.title, self.author]
    
    def __add__(self, other):
        """加法:obj + other"""
        if isinstance(other, Book):
            # 合并两本书的页数
            return Book(
                f"{self.title} & {other.title}",
                f"{self.author}, {other.author}",
                self.pages + other.pages
            )
        raise TypeError("只能与另一个Book对象相加")
    
    def __eq__(self, other):
        """相等比较:obj == other"""
        if isinstance(other, Book):
            return (self.title == other.title and 
                    self.author == other.author and 
                    self.pages == other.pages)
        return False
    
    def __lt__(self, other):
        """小于比较:obj < other"""
        if isinstance(other, Book):
            return self.pages < other.pages
        raise TypeError("只能与另一个Book对象比较")
    
    def __call__(self, page):
        """调用对象:obj()"""
        if 1 <= page <= self.pages:
            return f"跳转到《{self.title}》的第{page}页"
        raise ValueError(f"页码{page}超出范围(1-{self.pages})")
    
    def __del__(self):
        """析构方法:对象被销毁时调用"""
        print(f"《{self.title}》对象已销毁")

# 使用特殊方法
book1 = Book("Python编程", "张三", 500)
book2 = Book("Java编程", "李四", 600)

# __str__ 和 __repr__
print(book1)  # 'Python编程' by 张三
print(repr(book1))  # Book('Python编程', '张三', 500)

# __len__
print(f"页数:{len(book1)}")  # 500

# __getitem__ 和 __setitem__
print(f"书名:{book1[0]}")  # Python编程
book1[1] = "张大三"  # 修改作者
print(f"修改后作者:{book1[1]}")  # 张大三

# __contains__
print("张三" in book1)  # False(已改为张大三)
print("张大三" in book1)  # True

# __add__
combined_book = book1 + book2
print(combined_book)  # 'Python编程 & Java编程' by 张大三, 李四
print(f"总页数:{len(combined_book)}")  # 1100

# __eq__ 和 __lt__
print(book1 == book2)  # False
print(book1 < book2)   # True(500 < 600)

# __call__
print(book1(100))  # 跳转到《Python编程》的第100页

# __del__
del book1  # 触发析构方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

# 13. 迭代器与生成器

# 13.1 迭代器

# 迭代器协议:实现 __iter__() 和 __next__() 方法

# 自定义迭代器
class NumberIterator:
    """数字迭代器:生成从start到end的数字"""
    
    def __init__(self, start, end, step=1):
        self.current = start
        self.end = end
        self.step = step
    
    def __iter__(self):
        """返回迭代器自身"""
        return self
    
    def __next__(self):
        """返回下一个元素,没有则抛出StopIteration"""
        if (self.step > 0 and self.current > self.end) or \
           (self.step < 0 and self.current < self.end):
            raise StopIteration
        
        # 保存当前值并更新
        value = self.current
        self.current += self.step
        return value

# 使用自定义迭代器
iterator = NumberIterator(1, 10, 2)

# 方式1:使用next()
print(next(iterator))  # 1
print(next(iterator))  # 3
print(next(iterator))  # 5

# 方式2:使用for循环(自动处理StopIteration)
for num in NumberIterator(10, 0, -2):
    print(num, end=" ")  # 10 8 6 4 2
print()

# 内置迭代器
# 字符串迭代器
s = "Python"
str_iter = iter(s)
print(next(str_iter))  # P
print(next(str_iter))  # y

# 列表迭代器
lst = [1, 2, 3]
lst_iter = iter(lst)
print(list(lst_iter))  # [1, 2, 3]
# 迭代器只能遍历一次
print(list(lst_iter))  # []

# 字典迭代器
d = {"a": 1, "b": 2, "c": 3}
# 键迭代器
key_iter = iter(d)
print(next(key_iter))  # a

# 值迭代器
value_iter = iter(d.values())
print(next(value_iter))  # 1

# 键值对迭代器
item_iter = iter(d.items())
print(next(item_iter))  # ('a', 1)

# 无限迭代器
import itertools

# 计数迭代器
counter = itertools.count(10, 2)  # 从10开始,步长2
print(next(counter))  # 10
print(next(counter))  # 12
print(next(counter))  # 14

# 循环迭代器
cycle_iter = itertools.cycle(["A", "B", "C"])
print(next(cycle_iter))  # A
print(next(cycle_iter))  # B
print(next(cycle_iter))  # C
print(next(cycle_iter))  # A

# 重复迭代器
repeat_iter = itertools.repeat("Hello", 3)
print(list(repeat_iter))  # ['Hello', 'Hello', 'Hello']

# 迭代器工具函数
# 1. enumerate:带索引的迭代器
fruits = ["apple", "banana", "cherry"]
for idx, fruit in enumerate(fruits, start=1):
    print(f"{idx}. {fruit}")

# 2. zip:多序列迭代器
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
for name, age in zip(names, ages):
    print(f"{name}: {age}岁")

# 3. filter:过滤迭代器
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))  # [2, 4, 6, 8, 10]

# 4. map:映射迭代器
squares = map(lambda x: x**2, numbers)
print(list(squares))  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

# 13.2 生成器

# 生成器函数:使用yield关键字
def number_generator(start, end, step=1):
    """生成从start到end的数字(生成器函数)"""
    current = start
    while (step > 0 and current <= end) or (step < 0 and current >= end):
        yield current  # 暂停执行,返回值
        current += step  # 恢复执行时从此处继续

# 使用生成器
gen = number_generator(1, 10, 2)
print(type(gen))  # <class 'generator'>

# 方式1:迭代
for num in gen:
    print(num, end=" ")  # 1 3 5 7 9
print()

# 方式2:next()
gen2 = number_generator(10, 0, -2)
print(next(gen2))  # 10
print(next(gen2))  # 8
print(next(gen2))  # 6

# 生成器表达式(简化版生成器)
# 语法:(expression for item in iterable if condition)
square_gen = (x**2 for x in range(10))
print(list(square_gen))  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 生成器vs列表:内存效率对比
import sys

# 列表:一次性创建所有元素
large_list = [x for x in range(1000000)]
print(f"列表内存占用: {sys.getsizeof(large_list)} 字节")

# 生成器:按需生成元素
large_gen = (x for x in range(1000000))
print(f"生成器内存占用: {sys.getsizeof(large_gen)} 字节")

# 无限生成器
def infinite_counter(start=0):
    """无限计数器生成器"""
    current = start
    while True:
        yield current
        current += 1

# 使用无限生成器(配合itertools.islice)
import itertools
counter = infinite_counter(10)
# 取前5个值
for num in itertools.islice(counter, 5):
    print(num, end=" ")  # 10 11 12 13 14
print()

# 生成器的高级用法:发送值和关闭
def interactive_generator():
    """交互式生成器:接收外部值"""
    print("生成器启动")
    while True:
        # 接收发送的值
        received = yield "等待输入..."
        if received is None:
            break
        yield f"你输入了: {received}"

# 使用交互式生成器
gen = interactive_generator()
print(next(gen))  # 生成器启动 -> 等待输入...
print(gen.send("Hello"))  # 你输入了: Hello
print(next(gen))  # 等待输入...
print(gen.send(123))  # 你输入了: 123
gen.close()  # 关闭生成器
# next(gen)  # StopIteration

# 生成器管道(数据处理流水线)
def read_numbers(filename):
    """读取数字的生成器"""
    with open(filename, 'r') as f:
        for line in f:
            yield int(line.strip())

def filter_even(numbers):
    """过滤偶数的生成器"""
    for num in numbers:
        if num % 2 == 0:
            yield num

def square_numbers(numbers):
    """平方的生成器"""
    for num in numbers:
        yield num ** 2

# 创建生成器管道
# 1. 先创建测试文件
with open('numbers.txt', 'w') as f:
    for i in range(10):
        f.write(f"{i}\n")

# 2. 处理数据(按需处理,内存高效)
pipeline = square_numbers(filter_even(read_numbers('numbers.txt')))
for result in pipeline:
    print(result, end=" ")  # 0 4 16 36 64
print()

# 生成器的好处:
# 1. 延迟计算:按需生成值,节省内存
# 2. 简化代码:无需手动实现迭代器协议
# 3. 流水线处理:适合大数据处理
# 4. 状态保留:暂停/恢复执行,保留状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

# 14. 装饰器

# 14.1 装饰器基础

# 装饰器本质:接收函数作为参数,返回新函数的函数
import functools
# 简单装饰器
def simple_decorator(func):
    """简单的装饰器:记录函数调用"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        """包装函数:增强原函数功能"""
        print(f"调用函数: {func.__name__}")
        print(f"位置参数: {args}")
        print(f"关键字参数: {kwargs}")
        
        # 调用原函数
        result = func(*args, **kwargs)
        
        print(f"函数 {func.__name__} 执行完成,返回值: {result}")
        return result
    
    return wrapper

# 使用装饰器(语法糖@)
@simple_decorator
def multiply(a, b):
    """乘法函数"""
    return a * b

print(multiply(4, 6))

# 装饰器叠加
def timing_decorator(func):
    """计时装饰器:统计函数执行时间"""
    import time
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"函数 {func.__name__} 执行耗时: {end - start:.6f}秒")
        return result
    return wrapper

# 叠加多个装饰器(执行顺序:从上到下)
@simple_decorator
@timing_decorator
def slow_function(seconds):
    """耗时函数"""
    import time
    time.sleep(seconds)
    return f"休眠了{seconds}秒"

slow_function(0.1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# 14.2 带参数的装饰器

# 带参数的装饰器:装饰器工厂函数
def repeat_decorator(num_times):
    """装饰器工厂:重复执行函数指定次数"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            results = []
            for i in range(num_times):
                print(f"执行第{i+1}次")
                result = func(*args, **kwargs)
                results.append(result)
            return results
        return wrapper
    return decorator

# 使用带参数的装饰器
@repeat_decorator(num_times=3)
def say_hello(name):
    """打招呼函数"""
    return f"Hello, {name}!"

print(say_hello("Alice"))

# 装饰器类(替代函数装饰器)
class CountCallsDecorator:
    """计数装饰器类:统计函数调用次数"""
    
    def __init__(self, func):
        functools.update_wrapper(self, func)
        self.func = func
        self.call_count = 0
    
    def __call__(self, *args, **kwargs):
        self.call_count += 1
        print(f"函数 {self.func.__name__} 已调用 {self.call_count} 次")
        return self.func(*args, **kwargs)

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

print(greet("Bob"))
print(greet("Charlie"))
print(f"总调用次数: {greet.call_count}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 14.3 装饰器进阶应用

# 1. 缓存装饰器(记忆化)
def cache_decorator(func):
    """缓存装饰器:缓存函数调用结果"""
    cache = {}
    
    @functools.wraps(func)
    def wrapper(*args):
        # 仅缓存位置参数(简化版)
        if args not in cache:
            cache[args] = func(*args)
            print(f"缓存未命中,计算 {func.__name__}{args}")
        else:
            print(f"缓存命中,直接返回 {func.__name__}{args}")
        return cache[args]
    
    # 添加清除缓存的方法
    wrapper.clear_cache = lambda: cache.clear()
    return wrapper

@cache_decorator
def fibonacci(n):
    """斐波那契数列(递归版)"""
    if n <= 1:
        return n
    return fibonacci(n-1) + fibonacci(n-2)

# 测试缓存
print(fibonacci(10))  # 首次计算,缓存未命中
print(fibonacci(10))  # 缓存命中
fibonacci.clear_cache()  # 清除缓存
print(fibonacci(10))  # 重新计算

# 使用functools.lru_cache(标准库缓存装饰器)
@functools.lru_cache(maxsize=128)
def fibonacci_optimized(n):
    """斐波那契数列(优化版)"""
    if n <= 1:
        return n
    return fibonacci_optimized(n-1) + fibonacci_optimized(n-2)

print(fibonacci_optimized(30))
print(fibonacci_optimized.cache_info())  # 查看缓存信息
fibonacci_optimized.cache_clear()  # 清除缓存

# 2. 类型检查装饰器
def type_check_decorator(**type_map):
    """类型检查装饰器:检查函数参数类型"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 检查位置参数
            func_args = func.__code__.co_varnames[:func.__code__.co_argcount]
            for i, (arg_name, arg_value) in enumerate(zip(func_args, args)):
                if arg_name in type_map and not isinstance(arg_value, type_map[arg_name]):
                    raise TypeError(
                        f"参数 {arg_name} 类型错误,期望 {type_map[arg_name].__name__},实际 {type(arg_value).__name__}"
                    )
            
            # 检查关键字参数
            for arg_name, arg_value in kwargs.items():
                if arg_name in type_map and not isinstance(arg_value, type_map[arg_name]):
                    raise TypeError(
                        f"参数 {arg_name} 类型错误,期望 {type_map[arg_name].__name__},实际 {type(arg_value).__name__}"
                    )
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

@type_check_decorator(a=int, b=int)
def add(a, b):
    return a + b

print(add(10, 20))  # 正常
try:
    add(10, "20")  # 类型错误
except TypeError as e:
    print(f"类型检查触发: {e}")

# 3. 权限验证装饰器
def permission_required(permission):
    """权限验证装饰器:检查用户是否有指定权限"""
    def decorator(func):
        @functools.wraps(func)
        def wrapper(user, *args, **kwargs):
            # 模拟用户权限检查
            user_permissions = getattr(user, 'permissions', [])
            if permission not in user_permissions:
                raise PermissionError(f"用户 {user.name} 缺少权限: {permission}")
            return func(user, *args, **kwargs)
        return wrapper
    return decorator

# 测试权限装饰器
class User:
    def __init__(self, name, permissions):
        self.name = name
        self.permissions = permissions

@permission_required("admin")
def delete_user(user, user_id):
    return f"用户 {user.name} 删除了ID为{user_id}的用户"

admin_user = User("管理员", ["admin"])
normal_user = User("普通用户", ["read"])

print(delete_user(admin_user, 123))  # 正常
try:
    delete_user(normal_user, 123)  # 权限不足
except PermissionError as e:
    print(f"权限检查触发: {e}")

# 4. 注册装饰器(插件系统)
PLUGINS = {}

def register_plugin(name):
    """注册插件装饰器:将函数注册为插件"""
    def decorator(func):
        PLUGINS[name] = func
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 注册插件
@register_plugin("greet")
def greet_plugin(name):
    return f"Hello from plugin: {name}"

@register_plugin("calculate")
def calculate_plugin(a, b):
    return a * b

# 使用插件
print(f"已注册插件: {list(PLUGINS.keys())}")
print(PLUGINS["greet"]("Alice"))
print(PLUGINS["calculate"](10, 20))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

# 15. 常用内置函数

# 15.1 基础内置函数

# 1. 输入输出(保留核心功能,简化交互)
print("Hello, World!")  # 输出
name = input("请输入你的名字: ")  # 输入
print(f"你好,{name}!")  # 补充友好输出,避免输入后无反馈

# 2. 类型相关
print("===== 类型相关 =====")
print(type(10))          # <class 'int'>
print(type(3.14))        # <class 'float'>
print(type("hello"))     # <class 'str'>

# 类型转换
print(int("10"))         # 10
print(float(10))         # 10.0
print(str(3.14))         # "3.14"
print(list((1, 2, 3)))   # [1, 2, 3]
print(tuple([1, 2, 3]))  # (1, 2, 3)
print(set([1, 2, 2, 3])) # {1, 2, 3}

# 3. 数值操作
print("===== 数值操作 =====")
print(abs(-10))          # 绝对值:10
print(round(3.14159, 2)) # 四舍五入:3.14
print(min(1, 2, 3))      # 最小值:1
print(max(1, 2, 3))      # 最大值:3
print(sum([1, 2, 3, 4])) # 求和:10

# 4. 序列操作
print("===== 序列操作 =====")
print(len([1, 2, 3]))    # 长度:3
print(range(5))          # range(0, 5)
print(list(range(1, 6))) # [1, 2, 3, 4, 5]

# 5. 对象操作
print("===== 对象操作 =====")
lst = [1, 2, 3]
print(id(lst))           # 对象ID(内存地址)
print(hash("hello"))     # 哈希值
print(hex(255))          # 十六进制:0xff
print(oct(8))            # 八进制:0o10
print(bin(10))           # 二进制:0b1010

# 6. 逻辑判断
print("===== 逻辑判断 =====")
print(bool(0))           # False
print(bool("hello"))     # True
print(all([True, True])) # 所有为True:True
print(any([True, False]))# 任一为True:True

# 7. 变量操作(关键修改:避免输出海量数据)
print("===== 变量操作 =====")
# 注释掉输出全量globals/locals,改为输出关键信息
# print(dir())             # 注释:输出当前作用域变量列表(数据量大)
# print(globals())         # 注释:输出全局变量字典(数据量极大)
# print(locals())          # 注释:输出局部变量字典(数据量极大)
# 替代方案:只输出当前定义的核心变量
print("当前核心变量:", [var for var in dir() if not var.startswith('_')]) # 过滤系统变量

# 8. 帮助和文档(关键修改:避免输出大段帮助)
print("===== 帮助和文档 =====")
# print(help(print))       # 注释:输出print函数完整帮助(数据量大)
# 只查看文档字符串,或手动在Jupyter中执行 help(print)
print("print函数文档字符串摘要:", print.__doc__[:200]) # 只输出前200个字符
print("str类文档字符串:", str.__doc__[:200])          # 只输出前200个字符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

# 15.2 高级内置函数

# 1. 迭代相关
# map:映射函数到可迭代对象的每个元素
numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x**2, numbers))
print(squares)  # [1, 4, 9, 16]

# filter:过滤可迭代对象的元素
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

# zip:打包多个可迭代对象
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
zipped = list(zip(names, ages))
print(zipped)  # [('Alice', 25), ('Bob', 30), ('Charlie', 35)]

# enumerate:带索引的迭代
for idx, name in enumerate(names, start=1):
    print(f"{idx}. {name}")

# 2. 排序相关
# sorted:排序可迭代对象
unsorted = [3, 1, 4, 1, 5, 9]
sorted_asc = sorted(unsorted)
print(sorted_asc)  # [1, 1, 3, 4, 5, 9]

sorted_desc = sorted(unsorted, reverse=True)
print(sorted_desc)  # [9, 5, 4, 3, 1, 1]

# 按自定义键排序
people = [
    {"name": "Alice", "age": 25},
    {"name": "Bob", "age": 30},
    {"name": "Charlie", "age": 35}
]
sorted_by_age = sorted(people, key=lambda x: x["age"])
print(sorted_by_age)

# 3. 迭代器相关
# iter:创建迭代器
lst = [1, 2, 3]
lst_iter = iter(lst)
print(next(lst_iter))  # 1

# next:获取迭代器下一个元素
print(next(lst_iter))  # 2
print(next(lst_iter, "结束"))  # 3
print(next(lst_iter, "结束"))  # 结束

# 4. 函数相关
# callable:检查对象是否可调用
def func():
    pass

print(callable(func))    # True
print(callable(10))      # False
print(callable("hello")) # False

# getattr/setattr/hasattr:属性操作
class Person:
    def __init__(self, name):
        self.name = name

p = Person("Alice")
print(hasattr(p, "name"))    # True
print(getattr(p, "name"))    # Alice
setattr(p, "age", 25)
print(p.age)                 # 25
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68

# 15.3 内置函数最佳实践

# 1. 列表推导式替代map/filter(更易读)
numbers = [1, 2, 3, 4, 5]

# 替代map
squares = [x**2 for x in numbers]
# 替代filter
evens = [x for x in numbers if x % 2 == 0]
# 组合map+filter
even_squares = [x**2 for x in numbers if x % 2 == 0]

# 2. 使用sorted进行复杂排序
data = [
    ("Alice", 25, "A"),
    ("Bob", 30, "B"),
    ("Charlie", 25, "C")
]

# 按多个键排序(先按年龄,再按等级)
sorted_data = sorted(data, key=lambda x: (x[1], x[2]))
print(sorted_data)

# 3. 使用enumerate获取索引
fruits = ["apple", "banana", "cherry"]
for idx, fruit in enumerate(fruits, 1):
    print(f"第{idx}个水果:{fruit}")

# 4. 使用zip同时遍历多个序列
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]
scores = [85, 90, 88]

for name, age, score in zip(names, ages, scores):
    print(f"{name}: {age}岁, 分数{score}")

# 5. 安全使用eval(限制环境)
def safe_eval(expression):
    """安全的eval函数"""
    # 限制可用的内置函数
    safe_globals = {
        "__builtins__": {
            "abs": abs,
            "max": max,
            "min": min,
            "sum": sum
        }
    }
    return eval(expression, safe_globals)

print(safe_eval("abs(-10)"))  # 10
# print(safe_eval("__import__('os').system('ls')"))  # 安全:会报错

# 6. 使用 all / any 简化条件判断
# 检查所有元素是否满足条件
numbers = [2, 4, 6, 8]
all_even = all(x % 2 == 0 for x in numbers)
print(f"全是偶数: {all_even}")  # True

# 检查任一元素满足条件
has_negative = any(x < 0 for x in numbers)
print(f"有负数: {has_negative}")  # False

# 7. 使用 reversed 反向遍历
for num in reversed([1, 2, 3, 4]):
    print(num, end=" ")  # 4 3 2 1
print()

# 8. 使用 slice 简化切片操作
lst = list(range(10))
# 定义切片规则
every_other = slice(0, 10, 2)
reverse_slice = slice(None, None, -1)

print(lst[every_other])   # [0, 2, 4, 6, 8]
print(lst[reverse_slice]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

# 16. 总结

# 16.1 基础语法核心回顾

  1. 语法风格

    • Python 以缩进划分代码块,简洁易读
    • 注释:# 单行注释,""""""/'''''' 多行注释
    • 语句可分行,括号内可自动换行
  2. 变量与数据类型

    • 动态类型,无需声明类型
    • 核心类型:数字、字符串、列表、元组、集合、字典
    • 灵活的类型转换与运算
  3. 流程控制

    • 条件:if-elif-else、三元表达式、match-case
    • 循环:while、for,配合 break/continue/pass
    • 支持 for-else、while-else 结构
  4. 函数

    • 定义:def 关键字,支持默认、可变、关键字参数
    • 匿名函数:lambda 用于简单逻辑
    • 作用域:LEGB 规则,global/nonlocal 关键字
    • 高阶特性:闭包、偏函数、递归
  5. 数据结构

    • 列表:有序可变,支持索引、切片、增删改查
    • 元组:有序不可变,安全高效,可作字典键
    • 集合:无序唯一,支持交并补集,适合去重、成员判断
    • 字典:键值对映射,查找高效,Python3.7+ 有序
  6. 模块与包

    • 代码复用:import/from ... import
    • 标准库:math、random、datetime、os、sys
    • 包管理:__init__.py、相对/绝对导入
  7. 文件操作

    • 打开:open() + 模式,推荐 with 上下文管理器
    • 读写:read()/readline()/write()/writelines()
    • 常用格式:json、csv 结构化数据处理
  8. 异常处理

    • 捕获:try-except-else-finally
    • 抛出:raise,支持链式异常
    • 自定义异常:继承 Exception,业务更清晰
  9. 面向对象

    • 封装:私有属性/方法,控制访问
    • 继承:单/多继承,代码复用
    • 多态:统一接口,不同实现
    • 魔术方法:__init__/__str__/__iter__ 等
  10. 迭代器 & 生成器

    • 迭代器:实现 __iter__/__next__
    • 生成器:yield 延迟计算,内存高效
    • 生成器表达式:(x for x in ...)
  11. 装饰器

    • 无侵入增强函数功能:日志、计时、缓存、权限
    • 支持带参装饰器、装饰器类
    • 标准库:functools.wraps、lru_cache
  12. 常用内置函数

    • 迭代:map/filter/zip/enumerate
    • 计算:len/sum/min/max/sorted
    • 对象:type/isinstance/getattr/setattr

# 16.2 学习与编码建议

  1. 编码规范

    • 遵循 PEP 8:4 空格缩进,变量小写加下划线,类名大驼峰
    • 命名见名知意,拒绝无意义单字符
    • 适量注释,重点写“为什么”而非“做什么”
  2. 性能与习惯

    • 大数据用生成器而非列表
    • 成员判断优先用集合
    • 字典查找优于列表遍历
    • 文件/网络/数据库操作必用上下文管理器
  3. 排错思路

    • 先看报错类型与行号
    • 打印关键变量、使用 try-except 捕获异常
    • 利用 type()/isinstance() 排查类型问题
    • 复杂逻辑拆分小函数,单元测试验证
  4. 进阶方向

    • Web 开发:Flask、Django
    • 数据科学:NumPy、Pandas、Matplotlib
    • 自动化/运维:脚本、定时任务、API 对接
    • 爬虫/AI:Requests、Scrapy、机器学习基础

# 16.3 结束语

本教程从环境搭建、基础语法、数据类型、流程控制、函数、数据结构、模块包、文件操作、异常处理、面向对象、迭代器生成器、装饰器、内置函数全面覆盖 Python 基础语法。

Python 核心魅力在于简洁、优雅、强大,多写代码、多做小项目、多看官方文档,就能快速从入门到熟练。

最近更新: 2026/2/25
 |  Copyright © -Present Kelsen All Rights Reserved. | Author KelsenJing
Python基础语法全面教程