Skip to content

Commit e19f897

Browse files
📝 更新Python文档,增强内容与示例
- 在上下文管理器部分新增`__enter__`和`__exit__`方法的详细说明,提升对异常处理的理解。 - 优化文件操作部分,增加参数详解和示例,增强文档的实用性与可读性。 - 更新`compile`、`eval`和`exec`函数的参数说明,提供更清晰的用法示例,提升学习效果。
1 parent a8ee444 commit e19f897

File tree

3 files changed

+112
-179
lines changed

3 files changed

+112
-179
lines changed

docs/docs/选择编程语言/Python/20类与对象.mdx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,11 +638,25 @@ __next__
638638
```python showLineNumbers
639639
class ContextManager(object):
640640
def __enter__(self):
641+
"""
642+
__enter__ 方法可以返回一个值,该值会被 `as` 关键字绑定到 `with` 语句的变量上。
643+
"""
641644
print("Entering")
645+
# 一个常见的做法是让 `__enter__` 返回上下文管理器对象本身。
642646
return self
643647

644648
def __exit__(self, exc_type, exc_value, traceback):
649+
"""
650+
__exit__ 方法接收三个参数:exc_type (异常类型), exc_value (异常值), traceback (堆栈信息)。如果 `with` 块中发生了异常,这些参数将包含异常信息。
651+
652+
如果 __exit__ 返回 True,则表示该异常已被处理,不会再次向上抛出。
653+
如果 __exit__ 返回 False (或 None),则异常会继续传播。
654+
"""
645655
print("Exiting")
656+
if exc_type is not None:
657+
print(f" Exception Type: {exc_type.__name__}")
658+
print(f" Exception Value: {exc_value}")
659+
return True # 阻止异常向外传播
646660

647661
with ContextManager():
648662
print("inside operate")
@@ -651,6 +665,16 @@ Entering
651665
inside operate
652666
Exiting
653667
"""
668+
with ContextManager():
669+
print(1 / 0) # 会引发 ZeroDivisionError
670+
print("程序继续执行") # 如果 __exit__ 返回 True,这行会被执行
671+
"""
672+
Entering
673+
Exiting
674+
Exception Type: ZeroDivisionError
675+
Exception Value: division by zero
676+
程序继续执行
677+
"""
654678
```
655679

656680
:::info

docs/docs/选择编程语言/Python/29文件操作.mdx

Lines changed: 23 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,20 @@ title: 文件操作
1717

1818
函数签名:`open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)`
1919

20-
### 参数详解
21-
2220
- **`file`**
2321
- 一个 [path-like object](https://docs.python.org/zh-cn/3/glossary.html#term-path-like-object),表示将要打开的文件的路径(绝对路径或相对当前工作目录的路径)。
2422
- 也可以是要封装文件对应的整数类型文件描述符(如果给出的是文件描述符,则当返回的 I/O 对象关闭时它也会关闭,除非将 `closefd` 设为 `False`)。
2523

2624
- **`mode`**
2725
- 一个指明文件打开模式的可选字符串,默认为 `'r'` (以文本模式读取)。
28-
- 详细模式字符及含义见下表。
29-
30-
| 字符 | 含意 |
31-
|------|----------------------------|
32-
| `'r'` | 读取(默认) |
33-
| `'w'` | 写入,并先截断文件(清空) |
34-
| `'x'` | 排它性创建,如果文件已存在则失败 |
35-
| `'a'` | 打开文件用于写入,如果文件存在则在末尾追加 |
36-
| `'b'` | 二进制模式 |
37-
| `'t'` | 文本模式(默认) |
38-
| `'+'` | 打开用于更新(读取与写入) |
26+
- 详细模式字符及含义见下表。参数 mode 可以叠加使用,例如 `rb` 表示以二进制模式读取并写入。
27+
- `'r'`:读取(默认)
28+
- `'w'`:写入,并先截断文件(清空)
29+
- `'x'`:排它性创建,如果文件已存在则失败
30+
- `'a'`:打开文件用于写入,如果文件存在则在末尾追加
31+
- `'b'`:二进制模式
32+
- `'t'`:文本模式(默认)
33+
- `'+'`:打开用于更新(读取与写入)
3934

4035
- **`buffering`**
4136
- 一个可选的整数,用于设置缓冲策略。
@@ -50,17 +45,18 @@ title: 文件操作
5045

5146
- **`errors`**
5247
- 可选字符串参数,指定如何处理编码和解码错误,不能在二进制模式下使用。
53-
- 常见值:`'strict'` (默认,引发 `ValueError`)、`'ignore'``'replace'``'surrogateescape'``'xmlcharrefreplace'``'backslashreplace'``'namereplace'`
48+
- `'strict'` (默认,引发 `ValueError`)
49+
- `'ignore'`:忽略错误,继续执行。
50+
- `'replace'`:替换为 `?`
51+
- `'surrogateescape'`:使用代理字符。
52+
- `'xmlcharrefreplace'`:替换为 XML 字符引用。
53+
- `'backslashreplace'`:替换为反斜杠。
54+
- `'namereplace'`:替换为名称。
5455

5556
- **`newline`**
56-
- 决定如何解析来自流的换行符。可为 `None`, `''`, `'
57-
'`, `'
58-
'``'
59-
'`。
60-
- 读取时:`None` 启用通用换行模式并转换为 `'
61-
'``''` 启用通用换行模式但不转换;其他值则按给定字符串终止行且不转换。
62-
- 写入时:`None` 转换为系统默认行分隔符 `os.linesep``''` 或 `'
63-
'` 不进行翻译;其他值转换为给定字符串。
57+
- 决定如何解析来自流的换行符。可为 `None`, `''`, `'\n'`, `'\r'``'\r\n'`
58+
- 读取时:`None` 启用通用换行模式并转换为 `'\n'``''` 启用通用换行模式但不转换;其他值则按给定字符串终止行且不转换。
59+
- 写入时:`None` 转换为系统默认行分隔符 `os.linesep``''``'\n'` 不进行翻译;其他值转换为给定字符串。
6460

6561
- **`closefd`**
6662
- 如果为 `False``file` 是文件描述符,则当文件对象关闭时,底层文件描述符保持打开状态。如果 `file` 是文件名,则 `closefd` 必须为 `True`(默认值)。
@@ -69,10 +65,7 @@ title: 文件操作
6965
- 一个可调用的自定义开启器。通过 `opener(file, flags)` 获取文件对象的基础文件描述符。
7066

7167

72-
73-
## 文本文件操作
74-
75-
### 写入文件
68+
### 读写文本文件
7669

7770
使用 `'w'` 模式(写入并清空)、`'a'` 模式(追加写入)或 `'w+'` (读写并清空)模式打开文件进行写入。如果文件不存在,这些模式会自动创建文件。
7871

@@ -99,8 +92,6 @@ print(f.read()) # 输出:lo world. morning.
9992
f.close()
10093
```
10194

102-
### 读取文件
103-
10495
使用 `'r'` 模式(默认)或 `'r+'` (读写但不清空)模式打开文件进行读取。如果文件不存在,会引发 `FileNotFoundError`
10596

10697
```python showLineNumbers
@@ -124,12 +115,10 @@ for line in f:
124115
f.close()
125116
```
126117

127-
## 二进制文件操作
118+
### 读写二进制文件
128119

129120
当需要处理图片、音频、视频等非文本数据时,应以二进制模式(`'b'`)打开文件。
130121

131-
### 读写二进制数据
132-
133122
在二进制模式下,所有数据都以 `bytes` 对象形式读写,不进行任何编码或解码。
134123

135124
```python showLineNumbers
@@ -146,16 +135,14 @@ print(repr(f.read())) # 输出:b'...' (bytes representation)
146135
f.close()
147136
```
148137

149-
## 上下文管理器 (with 语句)
138+
## with 语句
150139

151140
`with` 语句是 Python 中处理文件(及其他需要资源清理的操作)的最佳实践。它确保文件在使用完毕后,无论是否发生异常,都会被正确关闭。
152141

153142
:::info `with` 语句的优势
154143
`with` 语句通过上下文管理器协议 (`__enter__``__exit__` 方法) 自动管理资源的获取和释放。它替代了传统的 `try...finally` 模式,使代码更简洁、更安全,有效避免了资源泄漏。
155144
:::
156145

157-
### 使用 `with open()`
158-
159146
这是打开文件的推荐方式。
160147

161148
```python showLineNumbers
@@ -171,116 +158,14 @@ finally:
171158
fp.close()
172159
```
173160

174-
### 自定义上下文管理器
175-
176-
你可以通过实现 `__enter__``__exit__` 方法来创建自己的上下文管理器。
177-
178-
```python showLineNumbers
179-
class ContextManager(object):
180-
def __enter__(self):
181-
print("Entering")
182-
183-
def __exit__(self, exc_type, exc_value, traceback):
184-
print("Exiting")
185-
186-
with ContextManager():
187-
print("Inside operate")
188-
# 输出:
189-
# Entering
190-
# Inside operate
191-
# Exiting
192-
```
193-
194-
#### `__enter__` 的返回值
195-
196-
`__enter__` 方法可以返回一个值,该值会被 `as` 关键字绑定到 `with` 语句的变量上。
197-
198-
```python showLineNumbers
199-
class ContextManagerWithReturn:
200-
def __enter__(self):
201-
print("Entering")
202-
return "my value" # 返回一个字符串
203-
204-
def __exit__(self, exc_type, exc_value, traceback):
205-
print("Exiting")
206-
207-
with ContextManagerWithReturn() as val:
208-
print(val)
209-
# 输出:
210-
# Entering
211-
# my value
212-
# Exiting
213-
```
214-
215-
一个常见的做法是让 `__enter__` 返回上下文管理器对象本身,就像文件对象那样。
216-
217-
#### 错误处理与 `__exit__`
218-
219-
`__exit__` 方法接收三个参数:`exc_type` (异常类型), `exc_value` (异常值), `traceback` (堆栈信息)。如果 `with` 块中发生了异常,这些参数将包含异常信息。
220161

221-
- 如果 `__exit__` 返回 `True`,则表示该异常已被处理,不会再次向上抛出。
222-
- 如果 `__exit__` 返回 `False` (或 `None`),则异常会继续传播。
223-
224-
```python showLineNumbers
225-
class ContextManagerWithErrorHandling:
226-
def __enter__(self):
227-
print("Entering")
228-
229-
def __exit__(self, exc_type, exc_value, traceback):
230-
print("Exiting")
231-
if exc_type is not None:
232-
print(f" Exception Type: {exc_type.__name__}")
233-
print(f" Exception Value: {exc_value}")
234-
return True # 阻止异常向外传播
235-
236-
with ContextManagerWithErrorHandling():
237-
print(1 / 0) # 会引发 ZeroDivisionError
238-
print("程序继续执行") # 如果 __exit__ 返回 True,这行会被执行
239-
# 输出:
240-
# Entering
241-
# Exiting
242-
# Exception Type: ZeroDivisionError
243-
# Exception Value: division by zero
244-
# 程序继续执行
245-
```
246-
247-
## memoryview:高效处理大型二进制数据
162+
## memoryview 函数
248163

249164
`memoryview` 函数主要用于需要高性能和低内存开销的场景,特别是在处理大型二进制数据时。它提供了一个“视图”来直接、高效地访问和操作底层对象的内存,而不需要为数据创建昂贵的副本。
250165

251166
考虑一个场景,你需要从二进制文件中读取大量结构化的记录(例如,每条记录包含一个整数和一个浮点数),并且可能需要修改它们。
252167

253-
### 传统低效方式
254-
255-
每次读取和解包一条记录都会创建新的 `bytes` 对象,效率低下。
256-
257-
```python showLineNumbers
258-
import struct
259-
260-
record_size = 4 + 8 # int (4 bytes) + double (8 bytes) = 12 bytes
261-
262-
# 假设 data.bin 已存在并有数据
263-
# 这里先创建一个模拟文件
264-
with open("data.bin", "wb") as f:
265-
for i in range(5): # 写入5条记录
266-
f.write(struct.pack('<id', i, i * 1.5))
267-
268-
with open("data.bin", "rb") as f:
269-
# 假设我们只关心文件中的第2条记录 (索引为1)
270-
f.seek(1 * record_size) # 定位到第2条记录的起始位置
271-
272-
# 读取12个字节,并将其转换为 bytes 对象
273-
record_bytes = f.read(record_size)
274-
275-
# 从 bytes 对象中解包数据
276-
# 注意:这里会创建一个新的 bytes 对象,并进行解包
277-
record_id, value = struct.unpack('<id', record_bytes)
278-
279-
print(f"Record ID: {record_id}, Value: {value}")
280-
# 输出:Record ID: 1, Value: 1.5
281-
```
282-
283-
### 使用 memoryview 优化
168+
传统低效方式每次读取和解包一条记录都会创建新的 `bytes` 对象,效率低下。
284169

285170
`memoryview` 允许我们一次性读取一个较大的块,然后通过“视图”来遍历和修改这块内存,避免不必要的数据拷贝。
286171

@@ -333,27 +218,3 @@ with open("data.bin", "rb") as f:
333218
# record_id, value = modified_structured_mv[i]
334219
# print(f"Modified Record {i}: ID={record_id}, Value={value}")
335220
```
336-
337-
## 文件清理
338-
339-
在使用文件操作时,经常需要在操作完成后清理创建的临时文件。
340-
341-
### 删除文件
342-
343-
使用 `os.remove()` 函数可以删除指定路径的文件。
344-
345-
```python showLineNumbers
346-
import os
347-
348-
# 清理测试文件
349-
if os.path.exists('test.txt'):
350-
os.remove('test.txt')
351-
if os.path.exists('binary.bin'):
352-
os.remove('binary.bin')
353-
if os.path.exists('my_file.txt'):
354-
os.remove('my_file.txt')
355-
if os.path.exists('data.bin'):
356-
os.remove('data.bin')
357-
```
358-
359-

0 commit comments

Comments
 (0)