Python 语法迁移笔记 — Java工程师版

定位:从 Java 到 Python 的快速迁移速查手册
适用:有编程基础、需要快速上手 Python 工程开发的开发者
核心原则:对比理解,而非从零学习


一、核心差异总览

先建立整体认知,Python 与 Java 的本质差异:

维度 Java Python
语言类型 静态类型,编译型 动态类型,解释型
语法风格 严格结构,大括号{} 缩进表示代码块
类型声明 String name = "Tom" name = "Tom"(无声明)
语句结束 分号; 换行即结束
命名规范 camelCase snake_case
入口方法 public static void main() 无强制入口,直接执行
空值 null None
布尔值 true / false True / False(首字母大写)
字符串 "" 不可变 "" 不可变,f"" 格式化
集合 List<T> 泛型 list 无泛型,元素类型随意
导入 import java.util.* import os, from os import path

二、基础语法

2.1 变量与类型

Python 是动态类型,不需要声明类型。但工程实践中必须写 Type Hints(FastAPI 强制依赖)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ========== 基础类型 ==========
name = "Alice" # str
age = 25 # int
height = 1.75 # float
is_vip = True # bool(注意首字母大写)
nothing = None # NoneType(类比 null)

# ========== Type Hints(工程必写)==========
name: str = "Alice"
age: int = 25
height: float = 1.75
is_vip: bool = True
result: None = None

# ========== 类型转换 ==========
s = str(123) # "123"
n = int("456") # 456(转换失败抛 ValueError)
f = float("3.14") # 3.14
b = bool(1) # True(0/空容器为 False,其余为 True)

# Java对照:
# String s = String.valueOf(123);
# int n = Integer.parseInt("456");

Truthy / Falsy 规则(判断条件时自动转换,比 Java 更宽松):

1
2
falsy = [0, 0.0, "", [], {}, set(), None]  # 这些在 if 判断中都为 False
# Java对照:只有 boolean 能进 if,Python 几乎所有类型都能

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
29
30
31
32
33
34
# ========== 定义方式 ==========
s1 = '单引号' # 灵活,引号不打架
s2 = "双引号"
s3 = '''多行
字符串''' # 三引号支持换行,也用于文档注释(docstring)

# ========== f-string 格式化(最常用)==========
name = "Tom"
age = 25
print(f"姓名:{name},年龄:{age},明年:{age + 1}") # 任意表达式都能塞进去

# ========== 常用方法 ==========
s = " Hello World "
s.strip() # "Hello World"(trim)
s.lower() # " hello world "
s.upper() # " HELLO WORLD "
s.startswith("He") # False(有空格)
s.find("World") # 9(找不到返回 -1)
s.replace("World", "Python") # " Hello Python "

# ========== 切片语法(核心!)==========
s = "Python"
s[0] # 'P'
s[-1] # 'n'(负数从末尾倒数)
s[0:3] # 'Pyt'(左闭右开)[0, 3)
s[2:] # 'thon'(从索引2到末尾)
s[:4] # 'Pyth'(从头到索引4)
s[::2] # 'Pto'(步长为2,隔一个取一个)
s[::-1] # 'nohtyP'(步长-1,字符串反转!)

# Java对照:
# s.substring(0, 3) → Python: s[0:3]
# s.charAt(0) → Python: s[0]
# new StringBuilder(s).reverse().toString() → Python: s[::-1]

2.3 输入输出

1
2
3
4
5
6
7
8
9
10
11
12
# ========== 输出 ==========
print("Hello", "World", sep="-") # Hello-World(sep指定分隔符)
print("第一行", end="") # end="" 不换行(默认end="\n")

# ========== 输入 ==========
name = input("请输入姓名:") # 返回 str(没有 Scanner 的 nextInt/nextDouble)
age = int(input("请输入年龄:")) # 需要手动转换类型

# Java对照:
# Scanner sc = new Scanner(System.in);
# String name = sc.nextLine();
# int age = sc.nextInt();

三、数据结构(核心中的核心)

Python 的四大容器,列表和字典是使用频率最高的

3.1 列表 List(类比 Java ArrayList)

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
# ========== 创建 ==========
arr = [1, 2, 3, 4, 5]
mixed = [1, "two", 3.0, True] # Python列表元素类型可以混用(不推荐工程实践)
empty = []

# ========== 访问与修改 ==========
arr[0] # 1
arr[-1] # 5(最后一个)
arr[0] = 100 # 修改

# ========== 常用操作 ==========
arr.append(6) # 尾部添加 [1,2,3,4,5,6]
arr.insert(0, 0) # 指定位置插入 [0,1,2,3,4,5,6]
arr.extend([7, 8]) # 批量添加 [0,1,2,3,4,5,6,7,8]
arr.remove(100) # 删除第一个匹配值(不存在抛异常)
popped = arr.pop() # 弹出末尾,返回被弹出的值
popped = arr.pop(0) # 弹出指定索引

# ========== 查找与判断 ==========
if 3 in arr: # 是否存在(Java: arr.contains(3))
print("找到了")
idx = arr.index(3) # 返回索引(不存在抛 ValueError)
count = arr.count(3) # 出现次数

# ========== 切片(不破坏原列表,返回新列表)==========
arr = [0, 1, 2, 3, 4, 5, 6, 7, 8]
arr[2:5] # [2, 3, 4]
arr[:3] # [0, 1, 2]
arr[5:] # [5, 6, 7, 8]
arr[::2] # [0, 2, 4, 6, 8](隔一个取)
arr[::-1] # [8, 7, 6, 5, 4, 3, 2, 1, 0](反转)
arr[:] # 浅拷贝(等价于 arr.copy())

# ========== 排序 ==========
arr.sort() # 原地排序,返回 None(类比 Collections.sort)
arr.sort(reverse=True) # 降序
new_arr = sorted(arr) # 返回新列表,原列表不变(类比 stream.sorted())

# 按自定义key排序
users = [("Tom", 25), ("Jerry", 20), ("Alice", 30)]
users.sort(key=lambda x: x[1]) # 按年龄排序
# Java对照:users.sort(Comparator.comparing(u -> u.age));

# ========== 列表推导式(List Comprehension,Python 灵魂语法!)==========
# 场景:把原列表每个元素平方
numbers = [1, 2, 3, 4, 5]

# 传统写法(不推荐)
squares = []
for n in numbers:
squares.append(n * n)

# 列表推导式(推荐!一行搞定)
squares = [n * n for n in numbers] # [1, 4, 9, 16, 25]

# 带过滤条件
evens = [n for n in numbers if n % 2 == 0] # [2, 4]

# 双重循环(笛卡尔积)
pairs = [(x, y) for x in [1, 2] for y in ['a', 'b']] # [(1,'a'), (1,'b'), (2,'a'), (2,'b')]

# 类比 Java Stream:
# numbers.stream().map(n -> n * n).collect(Collectors.toList());
# numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());

3.2 字典 Dict(类比 Java HashMap,使用频率最高!)

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
# ========== 创建 ==========
user = {"name": "Tom", "age": 25, "city": "Beijing"}
empty = {}
empty = dict() # 两种方式等价

# ========== 访问 ==========
user["name"] # "Tom"
user.get("name") # "Tom"(不存在返回 None,不抛异常)
user.get("gender", "unknown") # "unknown"(指定默认值)

# ========== 增删改 ==========
user["email"] = "tom@example.com" # 新增/修改
del user["city"] # 删除
popped = user.pop("age") # 删除并返回值

# ========== 遍历(面试高频!)==========
# 遍历键
for key in user:
print(key, user[key])

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

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

# ========== 合并字典 ==========
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
d3 = d1 | d2 # {"a": 1, "b": 3, "c": 4}(Python 3.9+,| 合并,后面覆盖前面)
d1 |= d2 # d1 原地更新

# ========== 字典推导式 ==========
numbers = [1, 2, 3, 4, 5]
square_dict = {n: n * n for n in numbers} # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# 按条件过滤
adults = {k: v for k, v in users.items() if v["age"] >= 18}

# ========== 默认字典(工程实用)==========
from collections import defaultdict

counter = defaultdict(int) # 值不存在时默认返回 0
counter["apple"] += 1 # 不需要先判断 key 是否存在!

groups = defaultdict(list) # 值不存在时默认返回 []
groups["fruit"].append("apple")

# Java对照:HashMap<String, Integer> counter = new HashMap<>();
# counter.put("apple", counter.getOrDefault("apple", 0) + 1);
# Python的defaultdict让这种操作变得优雅

3.3 元组 Tuple(不可变列表,类比不可变数组)

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
# ========== 特点:不可变,创建后不能修改 ==========
t = (1, 2, 3)
# t[0] = 100 # TypeError! 不可变

# ========== 使用场景 ==========
# 1. 函数返回多个值(最常用)
def get_user():
return "Tom", 25, "Beijing" # 自动打包成元组

name, age, city = get_user() # 自动解包!(Java需要自定义类或数组)

# 2. 作为字典的 key(列表不能当 key,因为不可哈希)
locations = {
(116.4, 39.9): "北京",
(121.5, 31.2): "上海"
}

# 3. 单元素元组(易错!)
wrong = (1) # 这是 int,不是元组!括号被当作数学运算符
right = (1,) # 必须加逗号,这才是元组

# ========== 命名元组(带字段名的元组)==========
from collections import namedtuple

User = namedtuple("User", ["name", "age", "city"])
u = User("Tom", 25, "Beijing")
print(u.name) # "Tom"(像对象一样访问,但内存开销极小)

# 现代替代方案:dataclass(更推荐,见面向对象章节)

3.4 集合 Set(类比 Java HashSet)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
s = {1, 2, 3, 3, 3}         # {1, 2, 3} 自动去重
empty = set() # 不能用 {}(那是空字典)

# ========== 集合运算(比 Java 简洁得多!)==========
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}

a | b # {1, 2, 3, 4, 5, 6} 并集
a & b # {3, 4} 交集
a - b # {1, 2} 差集
a ^ b # {1, 2, 5, 6} 对称差集

# ========== 实用场景 ==========
# 快速去重
items = [1, 2, 2, 3, 3, 3]
unique = list(set(items)) # [1, 2, 3](不保证顺序)

# 成员判断(O(1),比列表快)
if 3 in s: # 集合查找 O(1) vs 列表查找 O(n)
pass

四、流程控制

4.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
# ========== 基础 if/elif/else ==========
score = 85

if score >= 90:
grade = "A"
elif score >= 80: # elif = else if(更简洁)
grade = "B"
elif score >= 60:
grade = "C"
else:
grade = "D"

# ========== 三元表达式(条件表达式)==========
grade = "及格" if score >= 60 else "不及格"
# Java对照:String grade = score >= 60 ? "及格" : "不及格";

# ========== 多条件组合 ==========
# Python用 and / or / not(不用 && || !)
if age >= 18 and age <= 60 and not is_vip:
pass

# ========== 判断元素存在(Python特色)==========
# 不要用 arr == [] 或 len(arr) == 0
if not arr: # 判断列表为空(最Pythonic)
pass
if arr: # 判断列表非空
pass
if key in d: # 判断字典中有key(Java: d.containsKey(key))
pass

# ========== match/case(Python 3.10+,类比 Java switch)==========
status = 200
match status:
case 200:
print("OK")
case 404:
print("Not Found")
case 500 | 502 | 503: # 多值匹配
print("Server Error")
case _: # 默认分支
print("Unknown")

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
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
# ========== for 循环(遍历,非C语言风格)==========
# Python的for = Java的for-each
for i in [1, 2, 3]:
print(i)

# range() 生成数字序列(最常用)
for i in range(5): # 0, 1, 2, 3, 4(左闭右开)
print(i)

for i in range(1, 6): # 1, 2, 3, 4, 5
print(i)

for i in range(0, 10, 2): # 0, 2, 4, 6, 8(步长2)
print(i)

# 遍历带索引(enumerate)
arr = ["a", "b", "c"]
for idx, value in enumerate(arr): # (0, 'a'), (1, 'b'), (2, 'c')
print(f"{idx}: {value}")

for idx, value in enumerate(arr, 1): # 索引起始值设为1
print(f"{idx}: {value}")

# 同时遍历多个列表(zip)
names = ["Tom", "Jerry"]
ages = [20, 25]
for name, age in zip(names, ages): # ("Tom", 20), ("Jerry", 25)
print(f"{name} is {age}")

# ========== while 循环 ==========
count = 0
while count < 5:
count += 1 # Python没有 count++

# ========== 循环控制 ==========
for n in range(10):
if n == 3:
continue # 跳过当前迭代(同Java)
if n == 7:
break # 终止循环(同Java)
print(n)

# for-else(Python特色,else在循环正常结束时执行,break时跳过)
for n in range(5):
if n == 10: # 条件不满足,不会break
break
else:
print("循环正常完成,没有找到10") # 会执行

# 实用场景:判断列表中是否没有满足条件的元素
for item in items:
if item.is_valid():
break
else:
print("没有有效元素") # 所有元素都不满足时执行

五、函数

5.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
# ========== 基础定义 ==========
def greet(name: str) -> str: # Type Hints: 参数类型 -> 返回类型
"""返回问候语(这是文档字符串 docstring)"""
return f"Hello, {name}"

# ========== 多个返回值(自动打包成元组)==========
def get_min_max(arr: list[int]) -> tuple[int, int]:
return min(arr), max(arr) # 自动打包

minimum, maximum = get_min_max([3, 1, 4, 1, 5]) # 自动解包

# ========== 默认参数 ==========
def connect(host: str = "localhost", port: int = 3306, timeout: int = 30) -> None:
print(f"连接到 {host}:{port},超时:{timeout}s")

connect() # localhost:3306, 30
connect("192.168.1.1") # 192.168.1.1:3306, 30
connect(port=5432) # localhost:5432, 30(关键字参数跳过前面)
connect("10.0.0.1", timeout=10) # 10.0.0.1:3306, 10(位置+关键字混用)

# 重要:默认参数在函数定义时求值一次(易错陷阱)
def append_item(item, lst=[]): # ❌ 不要这样做!
lst.append(item)
return lst

append_item(1) # [1]
append_item(2) # [1, 2] —— lst被复用了!

# 正确做法
def append_item(item, lst=None): # ✅ 用 None 做占位
if lst is None:
lst = []
lst.append(item)
return lst

5.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
29
30
31
32
33
34
35
36
37
38
# ========== *args —— 接收多余的位置参数,打包成元组 ==========
def total(*numbers: int) -> int: # numbers 是 tuple
return sum(numbers)

total(1, 2, 3, 4) # 10
total() # 0
total(*[1, 2, 3]) # 6(* 解包列表,等价于 total(1, 2, 3))

# ========== **kwargs —— 接收多余的关键字参数,打包成字典 ==========
def build_profile(**kwargs: str) -> dict: # kwargs 是 dict
return kwargs

build_profile(name="Tom", city="Beijing") # {"name": "Tom", "city": "Beijing"}

# 解包字典传入
data = {"name": "Jerry", "age": "20"}
build_profile(**data) # 等价于 build_profile(name="Jerry", age="20")

# ========== 组合使用(常见模式)==========
def flexible(*args, **kwargs):
"""接收任意参数"""
print(f"位置参数:{args}")
print(f"关键字参数:{kwargs}")

flexible(1, 2, 3, name="Tom", age=25)
# 位置参数:(1, 2, 3)
# 关键字参数:{'name': 'Tom', 'age': 25}

# ========== 参数顺序(必须遵守!)==========
def func(a, b, /, c, d, *args, e, f, **kwargs):
"""
a, b —— 仅位置参数(/ 之前)
c, d —— 位置或关键字
*args —— 接收多余位置参数
e, f —— 仅关键字参数(* 之后)
**kwargs—— 接收多余关键字参数
"""
pass

5.3 Lambda 表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 语法:lambda 参数: 表达式
square = lambda x: x * x

# 实际场景:配合 sorted/map/filter
students = [("Tom", 85), ("Jerry", 72), ("Alice", 91)]

# 按分数排序
students.sort(key=lambda s: s[1]) # 升序
students.sort(key=lambda s: s[1], reverse=True) # 降序

# 提取所有分数
scores = list(map(lambda s: s[1], students))

# 筛选优秀生
excellent = list(filter(lambda s: s[1] >= 90, students))

# ========== lambda vs 列表推导式 ==========
# map/filter 可以用推导式替代(更推荐推导式)
scores = [s[1] for s in students] # 替代 map
excellent = [s for s in students if s[1] >= 90] # 替代 filter

5.4 装饰器(重点!FastAPI 的核心机制)

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
# ========== 装饰器本质:接收函数,返回函数 ==========
import functools
import time

def timing(func):
"""计算函数执行时间的装饰器"""
@functools.wraps(func) # 保留原函数的元信息(name, docstring)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
elapsed = time.time() - start
print(f"{func.__name__} 耗时 {elapsed:.3f}s")
return result
return wrapper

# ========== 使用 @ 语法 ==========
@timing
def slow_function(n: int) -> int:
"""模拟耗时操作"""
time.sleep(0.1)
return n * n

slow_function(5) # 输出: slow_function 耗时 0.101s

# ========== 带参数的装饰器 ==========
def repeat(times: int): # 外层接收装饰器参数
def decorator(func): # 中层接收被装饰函数
@functools.wraps(func)
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator

@repeat(times=3)
def say_hello():
print("Hello!")

say_hello() # 输出 3 次 Hello!

# ========== 理解 @app.get("/") 的本质 ==========
# FastAPI中:
@app.get("/users")
def get_users(): ...

# 等价于:
def get_users(): ...
get_users = app.get("/users")(get_users)
# app.get("/users") 返回一个装饰器函数,然后装饰 get_users

六、面向对象

6.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
# ========== 基础类 ==========
class User:
# 类属性(所有实例共享,类比 Java static)
species = "Homo sapiens"

def __init__(self, name: str, age: int) -> None:
"""构造方法(类比 Java 构造器)"""
self.name = name # 实例属性(self 类比 Java this,但必须显式传递)
self._age = age # 约定:单下划线表示"受保护"(非强制)
self.__password = "" # 双下划线触发名称改写(private 效果)

def greet(self) -> str: # 实例方法第一个参数必须是 self
return f"Hi, I'm {self.name}"

@classmethod
def from_birth_year(cls, name: str, year: int) -> "User":
"""类方法(类比 Java static 工厂方法)cls 类比 Java 的类名"""
return cls(name, 2026 - year)

@staticmethod
def is_adult(age: int) -> bool:
"""静态方法(无 self/cls,纯工具函数)"""
return age >= 18

# ========== 继承 ==========
class Admin(User):
def __init__(self, name: str, age: int, level: int) -> None:
super().__init__(name, age) # 调用父类构造(不需要写父类名)
self.level = level

def greet(self) -> str: # 方法重写
base = super().greet() # 调用父类方法
return f"{base} [Admin Lv.{self.level}]"

# ========== 使用 ==========
user = User("Tom", 25)
print(user.greet()) # Hi, I'm Tom
print(User.is_adult(20)) # True(静态方法)

admin = Admin("Boss", 40, 5)
print(admin.greet()) # Hi, I'm Boss [Admin Lv.5]

6.2 魔术方法(Dunder Methods)

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
class Vector:
"""二维向量,演示常见魔术方法"""

def __init__(self, x: float, y: float) -> None:
self.x = x
self.y = y

# 字符串表示
def __str__(self) -> str: # print() 调用
return f"Vector({self.x}, {self.y})"

def __repr__(self) -> str: # 交互式环境/调试调用
return f"Vector({self.x!r}, {self.y!r})"

# 比较
def __eq__(self, other: object) -> bool:
if not isinstance(other, Vector):
return NotImplemented
return self.x == other.x and self.y == other.y

# 运算符重载
def __add__(self, other: "Vector") -> "Vector":
return Vector(self.x + other.x, self.y + other.y)

def __sub__(self, other: "Vector") -> "Vector":
return Vector(self.x - other.x, self.y - other.y)

# 长度/大小
def __len__(self) -> int: # len() 调用
return 2

# 可调用
def __call__(self, scale: float) -> "Vector":
"""让实例像函数一样被调用"""
return Vector(self.x * scale, self.y * scale)

# 使用
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(v1 == Vector(1, 2)) # True
print(v1(2)) # Vector(2, 4) —— 实例像函数一样调用!

6.3 Dataclass(Python 3.7+,工程强烈推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from dataclasses import dataclass, field
from typing import List

# ========== @dataclass 自动生成 __init__, __repr__, __eq__ 等 ==========
@dataclass
class User:
name: str
age: int
email: str = "" # 默认值
tags: List[str] = field(default_factory=list) # 可变默认值必须用default_factory

# 等价于手写一个几十行的类!
user = User("Tom", 25, "tom@example.com")
print(user) # User(name='Tom', age=25, email='tom@example.com', tags=[])

# ========== 进阶配置 ==========
@dataclass(frozen=True) # 不可变(类比 Java record / final)
class Point:
x: float
y: float

# @dataclass 的自动生成的内容:
# __init__, __repr__, __eq__, __hash__(可选), __dict__

七、文件 IO 与异常处理

7.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
52
53
54
55
56
57
58
59
60
61
62
# ========== 核心:with 语句(自动关闭资源)==========
# 读取整个文件
with open("data.txt", "r", encoding="utf-8") as f: # f 是文件对象
content = f.read() # 读取全部(大文件慎用)

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

# 写入文件
with open("output.txt", "w", encoding="utf-8") as f:
f.write("第一行\n")
f.write("第二行\n")
f.writelines(["第三行\n", "第四行\n"])

# 追加模式
with open("log.txt", "a", encoding="utf-8") as f:
f.write("新增日志\n")

# ========== 模式总结 ==========
# "r" 只读(默认)
# "w" 只写(覆盖)
# "a" 追加
# "x" 创建(文件存在则报错)
# "b" 二进制模式(如 "rb" 读图片)
# "+" 读写(如 "r+")

# ========== JSON 处理(RAG开发高频!)==========
import json

data = {"name": "Tom", "age": 25, "tags": ["AI", "Python"]}

# 写入 JSON
with open("user.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)

# 读取 JSON
with open("user.json", "r", encoding="utf-8") as f:
loaded = json.load(f) # 直接变成 dict/list

# 字符串互转
json_str = json.dumps(data, ensure_ascii=False) # dict → str
parsed = json.loads(json_str) # str → dict

# ========== CSV 处理 ==========
import csv

# 写入
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["name", "age", "city"])
writer.writerows([
["Tom", 25, "Beijing"],
["Jerry", 20, "Shanghai"]
])

# 读取
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f) # 返回字典形式
for row in reader:
print(row["name"], row["age"]) # 通过列名访问

7.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
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
# ========== 基础 try/except ==========
try:
result = 10 / 0
except ZeroDivisionError as e: # 捕获特定异常
print(f"除零错误: {e}")
except Exception as e: # 兜底(类比 Java catch Exception)
print(f"其他错误: {e}")
else:
print(f"结果: {result}") # 无异常时执行
finally:
print("无论如何都会执行") # 清理资源(类比 Java finally)

# ========== 常见异常类型 ==========
# ValueError —— 类型转换失败(int("abc"))
# KeyError —— 字典key不存在(d["不存在的key"])
# IndexError —— 列表索引越界
# FileNotFoundError —— 文件不存在
# TypeError —— 类型不匹配
# AttributeError —— 对象没有该属性

# ========== 自定义异常 ==========
class ValidationError(Exception):
"""参数校验失败"""
pass

def validate_age(age: int) -> None:
if age < 0 or age > 150:
raise ValidationError(f"年龄 {age} 不合法")

# ========== 上下文管理器(with 的本质)==========
# with 语句等价于:
manager = open("file.txt", "r")
enter_result = manager.__enter__()
try:
# 使用 enter_result
pass
finally:
manager.__exit__(None, None, None)

# 自定义上下文管理器
from contextlib import contextmanager

@contextmanager
def managed_resource(name: str):
print(f"获取资源:{name}")
resource = {"name": name}
try:
yield resource # 把资源交给 with 块
finally:
print(f"释放资源:{name}")

with managed_resource("db_connection") as conn:
print(f"使用资源:{conn}")

八、进阶特性

8.1 生成器 Generator(流式处理的核心)

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
# ========== yield 关键字 ==========
def count_up_to(n: int):
"""生成 1 到 n 的数字,惰性求值"""
i = 1
while i <= n:
yield i # 暂停,返回当前值;下次从这儿继续
i += 1

# 使用
for num in count_up_to(5):
print(num) # 1 2 3 4 5

# ========== 生成器 vs 列表 ==========
# 列表(一次性占用全部内存)
squares_list = [x * x for x in range(1000000)] # 内存占用大

# 生成器表达式(惰性求值,几乎不占内存)
squares_gen = (x * x for x in range(1000000)) # 用到时才计算

# ========== 实用场景:大文件逐行处理 ==========
def read_large_file(filepath: str):
"""逐行读取大文件,内存友好"""
with open(filepath, "r", encoding="utf-8") as f:
for line in f:
yield line.strip()

# 处理100万行日志也只需要常数内存
for line in read_large_file("huge.log"):
if "ERROR" in line:
print(line)

# ========== yield from(委托子生成器)==========
def flatten(nested):
"""展平嵌套列表"""
for item in nested:
if isinstance(item, list):
yield from flatten(item) # 委托给子生成器
else:
yield item

list(flatten([1, [2, [3, 4]], 5])) # [1, 2, 3, 4, 5]

8.2 迭代器协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# ========== 让自定义类可迭代 ==========
class CountDown:
def __init__(self, start: int) -> None:
self.start = start

def __iter__(self): # 返回迭代器
return self

def __next__(self): # 返回下一个值
if self.start <= 0:
raise StopIteration # 迭代结束信号
self.start -= 1
return self.start + 1

# 使用
for n in CountDown(5):
print(n) # 5 4 3 2 1

# ========== 实际更简洁的写法(生成器函数)==========
def countdown(start: int):
while start > 0:
yield start
start -= 1

九、Type Hints 详解(FastAPI 的基础)

9.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
from typing import Optional, Union, List, Dict, Tuple, Set, Any, Callable

# ========== 基础类型 ==========
name: str = "Tom"
count: int = 0
price: float = 9.99
flag: bool = True
anything: Any = "任意类型"

# ========== Optional —— 可能为 None ==========
def find_user(user_id: int) -> Optional[dict]: # 返回 dict 或 None
# 找不到返回 None
return None

# 等价于 Union[dict, None](Python 3.10+ 可直接写 dict | None)

# ========== Union —— 多种类型之一 ==========
def parse_value(value: str) -> Union[int, float, str]:
# 可能返回 int、float 或 str
pass

# Python 3.10+ 新语法(更简洁)
def parse_value(value: str) -> int | float | str:
pass

# ========== 容器类型 ==========
names: List[str] = ["Tom", "Jerry"] # 字符串列表
scores: Dict[str, int] = {"Tom": 85, "Jerry": 90} # 字典
point: Tuple[int, int] = (10, 20) # 元组
tags: Set[str] = {"AI", "Python"} # 集合

# ========== 函数类型 ==========
handler: Callable[[int, str], bool] # 接收(int, str),返回 bool 的函数

# ========== 类型别名 ==========
JsonDict = Dict[str, Any] # 定义别名
UserData = Dict[str, Union[str, int]]

def process(data: JsonDict) -> UserData:
pass

9.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
29
30
31
32
33
34
35
36
37
38
39
40
41
from typing import TypeVar, Generic

T = TypeVar("T") # 定义类型变量

class Box(Generic[T]): # 泛型类
def __init__(self, value: T) -> None:
self.value = value

def get(self) -> T:
return self.value

int_box = Box[int](42) # Box[int]
str_box = Box[str]("hello") # Box[str]

# ========== Pydantic 模型(FastAPI 的核心数据模型)==========
from pydantic import BaseModel, Field
from datetime import datetime

class User(BaseModel): # 继承 BaseModel
id: int
name: str = Field(min_length=1, max_length=50)
email: str = Field(pattern=r"^\S+@\S+\.\S+$") # 正则校验
age: int = Field(ge=0, le=150) # 范围校验
created_at: datetime = Field(default_factory=datetime.now)
tags: List[str] = []

# Pydantic 自动完成:
# 1. 类型转换和校验(请求参数自动验证)
# 2. JSON 序列化/反序列化
# 3. 生成 OpenAPI 文档

# 从 dict 创建(自动类型转换和校验)
user = User(id="1", name="Tom", email="tom@example.com", age="25")
print(user.id) # 1(自动转为 int)

# 校验失败会抛 ValidationError
# User(id=1, name="", email="invalid", age=200) # 全部校验失败

# 转 dict / JSON
user_dict = user.model_dump() # dict
user_json = user.model_dump_json() # JSON 字符串

十、模块与包管理

10.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
# ========== 导入方式 ==========
import os # 导入整个模块:os.path.exists()
from os import path # 导入特定成员:path.exists()
from os import path as p # 起别名:p.exists()
from os import * # 导入所有(不推荐,污染命名空间)

# 相对导入(包内模块之间)
from . import module # 同级目录
from .. import parent # 上级目录
from .utils import helper # 同级目录的 utils 模块

# ========== 常用标准库 ==========
import os # 操作系统接口
import sys # 系统参数和函数
import json # JSON 处理
import csv # CSV 处理
import re # 正则表达式
import time # 时间相关
from datetime import datetime, timedelta # 日期时间
import random # 随机数
import hashlib # 哈希算法
from pathlib import Path # 面向对象的路径操作
from collections import defaultdict, Counter, namedtuple # 增强容器
from typing import * # 类型提示工具
import unittest # 单元测试

10.2 项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
my_project/                     # 项目根
├── main.py # 入口文件
├── config.py # 配置
├── models/ # 数据模型包
│ ├── __init__.py # 包标识(可为空,Python 3.3+ 可选)
│ ├── user.py
│ └── document.py
├── services/ # 业务逻辑包
│ ├── __init__.py
│ ├── search.py
│ └── rag_engine.py
├── utils/ # 工具包
│ ├── __init__.py
│ ├── helpers.py
│ └── logger.py
├── tests/ # 测试
│ ├── __init__.py
│ └── test_search.py
├── requirements.txt # 依赖清单
└── README.md
1
2
3
4
5
6
7
8
# requirements.txt 示例
fastapi==0.115.0
uvicorn[standard]==0.32.0
pydantic==2.9.0
httpx==0.27.0
python-multipart==0.0.12

# 安装:pip install -r requirements.txt

十一、Pythonic 编程规范

11.1 命名规范(PEP 8)

类型 规范 示例
模块/包 全小写+下划线 my_module, package_name
类名 大驼峰 MyClass, DocumentStore
函数/方法 全小写+下划线 my_function, get_user_by_id
常量 全大写+下划线 MAX_SIZE, DEFAULT_TIMEOUT
私有属性 单下划线前缀 _internal_value
强私有 双下划线前缀 __password

11.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
29
30
31
32
33
34
35
36
37
38
39
# ✅ 列表推导式替代循环
evens = [x for x in range(10) if x % 2 == 0]

# ✅ 用 enumerate 获取索引+值
for idx, val in enumerate(items):
pass

# ✅ 用 zip 并行遍历
for name, score in zip(names, scores):
pass

# ✅ 用 with 管理资源
with open("file.txt") as f:
data = f.read()

# ✅ 用 dict.get() 提供默认值
value = d.get("key", "default")

# ✅ 判断空容器直接 if
if not items: # 而非 if len(items) == 0
pass

# ✅ EAFP 风格(请求原谅而非许可)
try:
value = d["key"] # 直接尝试
except KeyError:
value = "default"

# ❌ LBYL 风格(Python 中不够优雅)
if "key" in d: # 先判断再操作
value = d["key"]
else:
value = "default"

# ✅ 解包赋值
a, b = b, a # 交换变量(不需要临时变量)

first, *rest = [1, 2, 3, 4] # first=1, rest=[2, 3, 4]
first, *middle, last = [1, 2, 3, 4] # first=1, middle=[2, 3], last=4

十二、Java → Python 常见陷阱对照表

场景 Java 习惯 Python 正确做法
判断相等 == 比较对象引用 == 比较值(数值/字符串),is 比较身份
字符串拼接 "" + var 循环拼接 f-string"".join()
空判断 str == null / str.isEmpty() if not s: / if s:
深拷贝 new ArrayList<>(old) copy.deepcopy(old) 或切片 [:]
整数除法 5 / 2 = 2(整数除) 5 // 2 = 2(地板除),5 / 2 = 2.5(真除法)
作用域 for 循环变量块级作用域 for 循环变量泄漏到外部!
默认参数 自动每次创建新对象 默认参数只求值一次(用 None 占位)
多线程 Thread / synchronized GIL 限制,用多进程或 asyncio
switch switch/case Python 3.10+ match/case,或字典映射
getter/setter getXxx() / setXxx() @property 装饰器

作用域泄漏陷阱(重点!)

1
2
3
4
5
6
7
8
9
10
11
# Java:for循环变量是块级作用域
# Python:for循环变量会泄漏!

i = 100
for i in range(5): # i 被覆盖!
pass
print(i) # 4(不是100!)

# 解决方案:用新变量名
for idx in range(5): # 不用 i
pass

十三、速查卡( Cheat Sheet )

常用操作一句话

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
# 判断元素存在
if x in arr: pass

# 列表转字符串
",".join(["a", "b", "c"]) # "a,b,c"

# 字符串转列表
"a,b,c".split(",") # ["a", "b", "c"]

# 字典合并
d1 | d2 # Python 3.9+
{**d1, **d2} # 通用

# 列表去重(保序)
list(dict.fromkeys([1,2,2,3])) # [1, 2, 3]

# 多重赋值
a, b, c = 1, 2, 3

# 条件赋值
value = x if x > 0 else 0 # 三元表达式

# 链式比较
if 0 <= score <= 100: pass # 而非 if score >= 0 and score <= 100

# 解包
a, *b, c = [1, 2, 3, 4, 5] # a=1, b=[2,3,4], c=5

# 批量赋值相同值
a = b = c = []
# ⚠️ a/b/c 指向同一个列表!修改一个影响全部

# 字典按值排序
sorted(d.items(), key=lambda x: x[1], reverse=True)

# 字符串重复
"-" * 30 # "------------------------------"

# 列表复制
arr_copy = arr[:] # 浅拷贝
arr_copy = arr.copy() # 同上
arr_copy = list(arr) # 同上
import copy; arr_deep = copy.deepcopy(arr) # 深拷贝

# 查看对象所有方法
dir(str) # 列出字符串所有方法
help(str.split) # 查看 split 文档

十四、常用标准库速查

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
# ========== os / sys ==========
import os
os.path.exists("file.txt") # 文件是否存在
os.path.join("dir", "file.txt") # 拼接路径(跨平台)
os.makedirs("a/b/c", exist_ok=True) # 递归创建目录
os.listdir(".") # 列出目录内容
os.getenv("API_KEY") # 读环境变量

from pathlib import Path # 更现代的路径操作(推荐)
path = Path("data") / "users.json" # Path("data/users.json")
path.exists()
path.read_text(encoding="utf-8")
path.write_text("content", encoding="utf-8")

# ========== re 正则 ==========
import re
re.search(r"\d+", "abc123") # 搜索第一个匹配
re.findall(r"\d+", "a1b2c3") # 找到所有匹配 ['1', '2', '3']
re.sub(r"\d+", "X", "a1b2") # 替换 "aXbX"
re.match(r"\d+", "123abc") # 从开头匹配
re.split(r",", "a,b,c") # ['a', 'b', 'c']

# ========== datetime ==========
from datetime import datetime, timedelta
now = datetime.now() # 当前时间
ts = now.isoformat() # "2026-01-15T10:30:00"
parsed = datetime.fromisoformat(ts) # 解析
dt = now + timedelta(days=7, hours=2) # 时间运算

# ========== random ==========
import random
random.randint(1, 100) # 随机整数 [1, 100]
random.choice(["a", "b", "c"]) # 随机选一个
random.shuffle(arr) # 原地打乱
random.random() # 0.0 \x7e 1.0 浮点

# ========== collections ==========
from collections import Counter, deque

counter = Counter(["a", "b", "a", "c", "a"])
counter.most_common(2) # [('a', 3), ('b', 1)]

dq = deque(maxlen=100) # 固定长度双端队列(滑动窗口)
dq.append(1)
dq.appendleft(0)

使用建议:这份笔记不是教科书,是速查手册。建议先通读一遍建立整体认知,然后边写代码边查阅。重点掌握:列表推导式、字典操作、装饰器、生成器、Type Hints、Dataclass——这六项是后续 FastAPI + AI 开发的语法基石。


版本:v1.0 | 配套:Python练习题 + RAG/Agent学习路线

1