Skip to content

Instantly share code, notes, and snippets.

@KuRRe8
Last active June 6, 2025 17:35
Show Gist options
  • Save KuRRe8/36f63d23ef205a8e02b7b7ec009cc4e8 to your computer and use it in GitHub Desktop.
Save KuRRe8/36f63d23ef205a8e02b7b7ec009cc4e8 to your computer and use it in GitHub Desktop.
和Python使用有关的一些教程,按类别分为不同文件

Python教程

Python是一个新手友好的语言,并且现在机器学习社区深度依赖于Python,C++, Cuda C, R等语言,使得Python的热度稳居第一。本Gist提供Python相关的一些教程,可以直接在Jupyter Notebook中运行。

  1. 语言级教程,一般不涉及初级主题;
  2. 标准库教程,最常见的标准库基本用法;
  3. 第三方库教程,主要是常见的库如numpy,pytorch诸如此类,只涉及基本用法,不考虑新特性

其他内容就不往这个Gist里放了,注意Gist依旧由git进行版本控制,所以可以git clone 到本地,或者直接Google Colab\ Kaggle打开相应的ipynb文件

直接在网页浏览时,由于没有文件列表,可以按Ctrl + F来检索相应的目录,或者点击下面的超链接。

想要参与贡献的直接在评论区留言,有什么问题的也在评论区说 ^.^

目录-语言部分

目录-库部分

目录-具体业务库部分-本教程更多关注机器学习深度学习内容

目录-附录

  • sigh.md个人对于Python动态语言的看法
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python 上下文管理器 (`with` 语句) 与 `contextlib` 模块教程\n",
"\n",
"欢迎来到 Python 上下文管理器和 `contextlib` 模块的教程!`with` 语句是 Python 中一种优雅且强大的资源管理方式,它可以确保某些操作(如文件关闭、锁的释放)即使在发生异常时也能正确执行。本教程将深入探讨上下文管理器的工作原理、如何自定义上下文管理器,以及如何使用 `contextlib` 模块中的工具来更轻松地创建它们。\n",
"\n",
"**为什么使用 `with` 语句和上下文管理器?**\n",
"\n",
"1. **资源管理**:自动获取和释放资源(如文件、网络连接、数据库会话、锁等),确保即使发生错误,清理代码(通常在 `finally` 块中)也能被执行。\n",
"2. **代码简洁性**:避免了显式的 `try...finally` 结构,使代码更易读。\n",
"3. **封装设置和拆卸逻辑**:将资源的准备和清理逻辑封装在上下文管理器内部。\n",
"\n",
"**本教程将涵盖:**\n",
"\n",
"1. **回顾 `with` 语句的基本用法**\n",
"2. **上下文管理协议 (Context Management Protocol)**:`__enter__` 和 `__exit__`\n",
"3. **创建自定义上下文管理器 (基于类)**\n",
"4. **`contextlib` 模块简介**\n",
" * `@contextlib.contextmanager` 装饰器:使用生成器创建上下文管理器\n",
" * `contextlib.closing`:确保对象的 `close()` 方法被调用\n",
" * `contextlib.suppress`:临时抑制指定的异常\n",
" * `contextlib.ExitStack` 和 `AsyncExitStack`:动态管理多个上下文管理器\n",
"5. **异步上下文管理器 (Async Context Managers)**:`__aenter__` 和 `__aexit__` (简要回顾)\n",
"6. **实际应用场景**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 回顾 `with` 语句的基本用法\n",
"\n",
"你最常看到的 `with` 语句可能是用于文件操作:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"file_path = \"example_with_statement.txt\"\n",
"\n",
"# 使用 with 语句打开文件\n",
"try:\n",
" with open(file_path, \"w\") as f:\n",
" print(f\"File object type inside with: {type(f)}\")\n",
" f.write(\"Hello from the with statement!\\n\")\n",
" print(\"Wrote to file.\")\n",
" # 文件 f 会在退出 with 块时自动关闭,即使发生异常\n",
" # raise ValueError(\"Simulating an error inside with\") # 取消注释测试异常处理\n",
" print(f\"File '{file_path}' closed automatically: {f.closed}\")\n",
"except ValueError as e:\n",
" print(f\"Caught error: {e}\")\n",
" # 即使发生错误,文件仍然会被关闭\n",
" # 注意:此时 f 可能未定义,取决于异常发生的位置\n",
" # print(f\"File closed after error: {f.closed}\") # 这行可能会报错\n",
" # 更好的做法是在 finally 中检查,或者信任 with 语句\n",
" pass \n",
"\n",
"# 清理文件\n",
"import os\n",
"if os.path.exists(file_path):\n",
" os.remove(file_path)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"这里的 `open()` 函数返回的文件对象就是一个**上下文管理器 (context manager)**。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 上下文管理协议 (Context Management Protocol)\n",
"\n",
"任何实现了以下两个特殊方法的对象都可以作为上下文管理器:\n",
"\n",
"* **`__enter__(self)`**:\n",
" * 在进入 `with` 语句块之前被调用。\n",
" * 它的返回值(如果有的话)会赋给 `with ... as variable:` 中的 `variable`。\n",
" * 如果不需要在 `as` 子句中接收值,`__enter__` 可以不返回任何东西(即返回 `None`)。\n",
"\n",
"* **`__exit__(self, exc_type, exc_val, exc_tb)`**:\n",
" * 在退出 `with` 语句块时被调用,无论块内代码是正常完成还是发生异常。\n",
" * 参数:\n",
" * `exc_type`: 异常的类型(如果块内没有异常,则为 `None`)。\n",
" * `exc_val`: 异常的实例(如果块内没有异常,则为 `None`)。\n",
" * `exc_tb`: 回溯 (traceback) 对象(如果块内没有异常,则为 `None`)。\n",
" * **返回值**:\n",
" * 如果 `__exit__` 方法返回 `True`,则表示它已经处理了异常,异常会被“抑制”,不会向外传播。\n",
" * 如果 `__exit__` 方法返回 `False` (或 `None`,这是默认行为),则发生的任何异常都会在 `__exit__` 方法执行完毕后重新引发,由外部代码处理。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 创建自定义上下文管理器 (基于类)\n",
"\n",
"我们可以通过定义一个包含 `__enter__` 和 `__exit__` 方法的类来创建自己的上下文管理器。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time\n",
"\n",
"class Timer:\n",
" \"\"\"一个简单的计时器上下文管理器\"\"\"\n",
" def __init__(self, name=\"Default Timer\"):\n",
" self.name = name\n",
" self.start_time = None\n",
" print(f\"Timer '{self.name}': Initialized.\")\n",
"\n",
" def __enter__(self):\n",
" print(f\"Timer '{self.name}': __enter__ - Starting timer.\")\n",
" self.start_time = time.perf_counter()\n",
" return self # 返回自身,以便在 with 块内可以访问 Timer 实例的属性 (可选)\n",
"\n",
" def __exit__(self, exc_type, exc_val, exc_tb):\n",
" end_time = time.perf_counter()\n",
" elapsed_time = end_time - self.start_time\n",
" print(f\"Timer '{self.name}': __exit__ - Elapsed time: {elapsed_time:.4f} seconds.\")\n",
" if exc_type:\n",
" print(f\" Timer '{self.name}': Exception occurred: {exc_type.__name__} - {exc_val}\")\n",
" # return False # 默认行为,不抑制异常\n",
"\n",
"print(\"--- Testing Timer context manager (normal execution) ---\")\n",
"with Timer(\"MyOperation\") as t:\n",
" print(f\" Inside with block for timer '{t.name}'. Accessing start_time (approx): {t.start_time}\")\n",
" time.sleep(0.5)\n",
" print(\" Work inside with block done.\")\n",
"\n",
"print(\"\\n--- Testing Timer context manager (with exception) ---\")\n",
"try:\n",
" with Timer(\"RiskyOperation\") as risky_t:\n",
" print(f\" Inside with block for timer '{risky_t.name}'.\")\n",
" time.sleep(0.2)\n",
" raise KeyError(\"Simulated key error!\")\n",
"except KeyError as e:\n",
" print(f\"Caught expected KeyError outside 'with': {e}\")\n",
"\n",
"# 示例:抑制异常\n",
"class SuppressErrorExample:\n",
" def __enter__(self):\n",
" print(\"SuppressErrorExample: Entering\")\n",
" return self\n",
" def __exit__(self, exc_type, exc_val, exc_tb):\n",
" print(\"SuppressErrorExample: Exiting\")\n",
" if isinstance(exc_val, TypeError):\n",
" print(f\" Suppressing TypeError: {exc_val}\")\n",
" return True # 抑制 TypeError\n",
" return False # 其他异常不抑制\n",
"\n",
"print(\"\\n--- Testing SuppressErrorExample (suppressing TypeError) ---\")\n",
"with SuppressErrorExample():\n",
" print(\" Trying to cause a TypeError...\")\n",
" _ = \"text\" + 5 # This will raise TypeError\n",
"print(\"After with block (TypeError was suppressed)\")\n",
"\n",
"print(\"\\n--- Testing SuppressErrorExample (not suppressing ValueError) ---\")\n",
"try:\n",
" with SuppressErrorExample():\n",
" print(\" Trying to cause a ValueError...\")\n",
" raise ValueError(\"This error won't be suppressed\")\n",
"except ValueError as e:\n",
" print(f\"Caught ValueError outside 'with' as expected: {e}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. `contextlib` 模块简介\n",
"\n",
"`contextlib` 模块提供了一些实用工具,用于处理上下文管理器和 `with` 语句。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.1 `@contextlib.contextmanager` 装饰器\n",
"\n",
"这个装饰器允许你使用一个简单的**生成器函数**来创建上下文管理器,而无需编写一个完整的类。\n",
"\n",
"**要求:**\n",
"* 被装饰的生成器函数必须**只 `yield` 一次**。\n",
"* `yield` 之前的部分代码相当于 `__enter__` 方法的逻辑。\n",
"* `yield` 语句产生的值会赋给 `with ... as variable:` 中的 `variable`。\n",
"* `yield` 之后的部分代码(通常在 `try...finally` 块中)相当于 `__exit__` 方法的逻辑,确保即使发生异常也能执行清理。\n",
"* 生成器内部发生的异常会正常传播,除非在 `finally` 块中被捕获或处理。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import contextlib\n",
"\n",
"@contextlib.contextmanager\n",
"def managed_file(filename, mode):\n",
" print(f\"@contextmanager: Acquiring file '{filename}' in mode '{mode}'\")\n",
" f = None\n",
" try:\n",
" f = open(filename, mode)\n",
" yield f # 这是 __enter__ 返回的值,也是生成器暂停的地方\n",
" print(f\"@contextmanager: Inside try block after yield (normal exit of 'with' body)\")\n",
" except Exception as e:\n",
" print(f\"@contextmanager: Exception caught inside generator: {e}\")\n",
" raise # 重新引发异常,除非你想抑制它\n",
" finally:\n",
" if f:\n",
" print(f\"@contextmanager: Releasing file '{filename}' (in finally)\")\n",
" f.close()\n",
"\n",
"file_path_cm = \"example_cm.txt\"\n",
"\n",
"print(\"--- Testing @contextmanager (normal execution) ---\")\n",
"with managed_file(file_path_cm, \"w\") as mf:\n",
" print(f\" Inside with: File object is {mf}\")\n",
" mf.write(\"Hello from @contextmanager!\")\n",
" print(f\" Inside with: File closed status: {mf.closed}\") # 应该是 False\n",
"print(f\"After with: Is file closed? {mf.closed}\") # 应该是 True\n",
"\n",
"print(\"\\n--- Testing @contextmanager (with exception) ---\")\n",
"try:\n",
" with managed_file(file_path_cm, \"r\") as mf_read: # 应该能读到刚才写的内容\n",
" print(f\" Inside with: Reading content: {mf_read.read().strip()}\")\n",
" raise ZeroDivisionError(\"Simulated error for @contextmanager\")\n",
"except ZeroDivisionError as e:\n",
" print(f\"Caught expected ZeroDivisionError outside 'with': {e}\")\n",
"\n",
"# 清理\n",
"if os.path.exists(file_path_cm):\n",
" os.remove(file_path_cm)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.2 `contextlib.closing(thing)`\n",
"\n",
"如果一个对象 `thing` 提供了 `close()` 方法但没有实现上下文管理协议(即没有 `__enter__` 和 `__exit__`),`closing(thing)` 会返回一个上下文管理器,它在退出时调用 `thing.close()`。\n",
"\n",
"这对于处理一些旧式的、只提供 `close()` 方法的资源很有用。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class OldResource:\n",
" def __init__(self, name):\n",
" self.name = name\n",
" self.is_closed = False\n",
" print(f\"OldResource '{self.name}': Created.\")\n",
" \n",
" def use(self):\n",
" if self.is_closed:\n",
" raise ValueError(\"Resource is closed\")\n",
" print(f\" OldResource '{self.name}': Being used.\")\n",
" \n",
" def close(self):\n",
" print(f\"OldResource '{self.name}': close() called.\")\n",
" self.is_closed = True\n",
"\n",
"print(\"--- Testing contextlib.closing --- \")\n",
"resource = OldResource(\"LegacyDB\")\n",
"\n",
"with contextlib.closing(resource) as r_closed:\n",
" # r_closed 就是 resource 本身\n",
" print(f\" Inside with: resource is r_closed: {resource is r_closed}\")\n",
" r_closed.use()\n",
"print(f\"After with: resource.is_closed = {resource.is_closed}\") # 应该是 True\n",
"\n",
"print(\"\\n--- Testing contextlib.closing with an error --- \")\n",
"resource2 = OldResource(\"LegacySocket\")\n",
"try:\n",
" with contextlib.closing(resource2) as r2_closed:\n",
" r2_closed.use()\n",
" raise RuntimeError(\"Error while using legacy resource\")\n",
"except RuntimeError as e:\n",
" print(f\"Caught expected RuntimeError: {e}\")\n",
"print(f\"After with (error): resource2.is_closed = {resource2.is_closed}\") # 仍然应该是 True"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.3 `contextlib.suppress(*exceptions)`\n",
"\n",
"返回一个上下文管理器,用于临时抑制指定的异常类型。在 `with` 块中,如果发生了列出的异常类型,它们会被捕获并静默处理,程序会正常继续执行 `with` 块之后的代码。\n",
"\n",
"**注意**:应谨慎使用,确保你确实想要忽略这些异常,而不是隐藏了重要的问题。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"--- Testing contextlib.suppress --- \")\n",
"\n",
"print(\"Attempting to delete a non-existent file (will suppress FileNotFoundError):\")\n",
"non_existent_file = \"no_such_file.txt\"\n",
"with contextlib.suppress(FileNotFoundError, PermissionError):\n",
" os.remove(non_existent_file)\n",
" print(f\" Code inside 'with' after os.remove attempt.\") # 这行会执行\n",
"print(\"After 'with' block, FileNotFoundError was suppressed.\")\n",
"\n",
"print(\"\\nAttempting an operation that causes TypeError (will not be suppressed):\")\n",
"try:\n",
" with contextlib.suppress(FileNotFoundError):\n",
" result = \"text\" + 10 # Raises TypeError\n",
" print(\" This line (inside with) will not be reached if TypeError occurs.\")\n",
"except TypeError as e:\n",
" print(f\"Caught TypeError outside 'with' as expected: {e}\")\n",
"print(\"After 'with' block for TypeError.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4.4 `contextlib.ExitStack` 和 `AsyncExitStack`\n",
"\n",
"`ExitStack` 是一个上下文管理器,它允许你以编程方式注册多个上下文管理器或清理函数,并在 `ExitStack` 本身退出时,以注册的相反顺序调用它们的 `__exit__` 方法或清理函数。\n",
"这对于动态管理一组不确定数量的资源非常有用。\n",
"\n",
"`AsyncExitStack` 是其异步版本,用于 `async with`。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class ResourceForStack:\n",
" def __init__(self, name):\n",
" self.name = name\n",
" def __enter__(self):\n",
" print(f\"ResourceForStack '{self.name}': Entering\")\n",
" return self\n",
" def __exit__(self, exc_type, exc_val, exc_tb):\n",
" print(f\"ResourceForStack '{self.name}': Exiting\")\n",
" def use(self):\n",
" print(f\" Using '{self.name}'\")\n",
"\n",
"def cleanup_function(resource_name):\n",
" print(f\"Cleanup function called for '{resource_name}'\")\n",
"\n",
"print(\"--- Testing contextlib.ExitStack --- \")\n",
"resources_to_manage = [\n",
" ResourceForStack(\"ResA\"),\n",
" ResourceForStack(\"ResB\")\n",
"]\n",
"\n",
"with contextlib.ExitStack() as stack:\n",
" print(\"Inside ExitStack 'with' block.\")\n",
" \n",
" # 动态进入上下文管理器\n",
" for res_obj in resources_to_manage:\n",
" r = stack.enter_context(res_obj)\n",
" r.use()\n",
" \n",
" # 注册一个简单的清理回调函数\n",
" # stack.callback(cleanup_function, \"DynamicResource1\")\n",
" # stack.callback(cleanup_function, \"DynamicResource2\")\n",
" # 或者使用 push (可以 unregister)\n",
" stack.push(lambda: cleanup_function(\"PushedCleanup1\"))\n",
" \n",
" print(\"Simulating work within ExitStack...\")\n",
" # 如果这里发生异常,所有已注册的 __exit__ 和回调仍会以相反顺序调用\n",
" # raise ValueError(\"Error inside ExitStack\") \n",
"\n",
"print(\"After ExitStack 'with' block. Resources should be released in reverse order of entry/push.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. 异步上下文管理器 (Async Context Managers) - 简要回顾\n",
"\n",
"对于异步编程 (`async/await`),上下文管理器需要使用异步版本的方法:\n",
"\n",
"* **`__aenter__(self)`**: 必须是一个 `async def` 方法,并且应该 `await` 异步操作。它返回的值(通常是 `awaitable` 解析后的值或 `self`)赋给 `async with ... as var` 中的 `var`。\n",
"* **`__aexit__(self, exc_type, exc_val, exc_tb)`**: 也必须是一个 `async def` 方法。\n",
"\n",
"`contextlib` 也提供了异步版本:\n",
"* `@contextlib.asynccontextmanager`\n",
"* `contextlib.AsyncExitStack`"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"\n",
"@contextlib.asynccontextmanager\n",
"async def async_managed_resource(name):\n",
" print(f\"AsyncCM '{name}': Acquiring resource (async)...\", flush=True)\n",
" await asyncio.sleep(0.1) # 模拟异步获取\n",
" try:\n",
" yield name # 值赋给 as 后面的变量\n",
" print(f\"AsyncCM '{name}': Inside try after yield (normal async with body exit).\", flush=True)\n",
" finally:\n",
" print(f\"AsyncCM '{name}': Releasing resource (async, in finally)...\", flush=True)\n",
" await asyncio.sleep(0.1) # 模拟异步释放\n",
"\n",
"async def use_async_cm():\n",
" print(\"--- Testing @asynccontextmanager ---\")\n",
" async with async_managed_resource(\"AsyncRes1\") as res_name:\n",
" print(f\" Inside async with: Got resource name '{res_name}'\", flush=True)\n",
" await asyncio.sleep(0.2)\n",
" print(\" Inside async with: Work done.\", flush=True)\n",
" print(\"After async with block.\", flush=True)\n",
"\n",
"# 为了在Jupyter中运行asyncio代码\n",
"if __name__ == '__main__': # 确保只在直接运行时执行,而不是导入时\n",
" # asyncio.run(use_async_cm()) # 标准运行方式\n",
" # 在Jupyter中,如果已经有事件循环,可能需要特殊处理。\n",
" # 通常,如果IPython版本够新,可以直接await顶层协程。\n",
" # 为了简单演示,这里不直接运行,或者需要nest_asyncio。\n",
" print(\"Async context manager example defined. Run in an async context.\")\n",
" # 如果想在notebook cell中直接运行, 你可以这样做:\n",
" # import nest_asyncio\n",
" # nest_asyncio.apply()\n",
" # asyncio.run(use_async_cm())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. 实际应用场景\n",
"\n",
"上下文管理器在多种场景下都非常有用:\n",
"\n",
"* **文件操作**:`open()` (最常见的例子)。\n",
"* **锁和同步原语**:`threading.Lock`, `multiprocessing.Lock` 等都支持 `with` 语句,确保锁被正确释放。\n",
" ```python\n",
" # import threading\n",
" # my_lock = threading.Lock()\n",
" # with my_lock:\n",
" # # 访问共享资源\n",
" # pass\n",
" ```\n",
"* **数据库连接和事务**:确保连接关闭和事务提交/回滚。\n",
" ```python\n",
" # import sqlite3\n",
" # with sqlite3.connect(\"mydb.db\") as conn: # 连接对象本身就是上下文管理器\n",
" # cursor = conn.cursor()\n",
" # # ... 执行SQL ...\n",
" # conn.commit() # 事务在正常退出时提交,异常时回滚\n",
" ```\n",
"* **网络连接**:确保套接字关闭。\n",
"* **临时改变状态**:例如,临时改变 `decimal` 模块的精度,或临时改变当前工作目录。\n",
" ```python\n",
" # import decimal\n",
" # @contextlib.contextmanager\n",
" # def local_decimal_precision(prec=28):\n",
" # ctx = decimal.getcontext()\n",
" # original_prec = ctx.prec\n",
" # ctx.prec = prec\n",
" # try:\n",
" # yield\n",
" # finally:\n",
" # ctx.prec = original_prec\n",
" # with local_decimal_precision(50):\n",
" # # 这里的 decimal 运算使用 50 位精度\n",
" # pass\n",
" ```\n",
"* **测试装置 (Fixtures)**:在测试中设置和拆卸测试环境。\n",
"* **性能计时和剖析**:如本教程中的 `Timer` 示例。\n",
"\n",
"## 总结\n",
"\n",
"上下文管理器和 `with` 语句是 Python 中进行健壮资源管理和封装设置/拆卸逻辑的关键工具。通过实现上下文管理协议或使用 `contextlib` 模块,你可以编写出更清晰、更可靠的代码。\n",
"\n",
"`contextlib` 模块,特别是 `@contextmanager` 装饰器,极大地简化了自定义上下文管理器的创建过程,使其更加易于使用和理解。"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.0"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 5
}
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

对动态语言Python的一些感慨

众所周知Python是完全动态的语言,体现在

  1. 类型动态绑定
  2. 运行时检查
  3. 对象结构内容可动态修改(而不仅仅是值)
  4. 反射
  5. 一切皆对象(instance, class, method)
  6. 可动态执行代码(eval, exec)
  7. 鸭子类型支持

动态语言的约束更少,对使用者来说更易于入门,但相应的也会有代价就是运行时开销很大,和底层汇编执行逻辑完全解耦不知道代码到底是怎么执行的。

而且还有几点是我认为较为严重的缺陷。下面进行梳理。

破坏了OOP的语义

较为流行的编程语言大多支持OOP编程范式。即继承和多态。同样,Python在执行简单任务时候可以纯命令式(Imperative Programming),也可以使用复杂的面向对象OOP。

但是,其动态特性破环了OOP的结构:

  1. 类型模糊:任何类型实例,都可以在运行时添加或者删除属性或者方法(相比之下静态语言只能在运行时修改它们的值)。经此修改的实例,按理说不再属于原来的类型,毕竟和原类型已经有了明显的区别。但是该实例的内建__class__属性依旧会指向原类型,这会给类型的认知造成困惑。符合一个class不应该只是名义上符合,而是内容上也应该符合。
  2. 破坏继承:体现在以下两个方面
    1. 大部分实践没有虚接口继承。abc模块提供了虚接口的基类ABC,经典的做法是让自己的抽象类继承自ABC,然后具体类继承自自己的抽象类,然后去实现抽象方法。但PEP提案认为Pythonic的做法是用typing.Protocol来取代ABC,具体类完全不继承任何虚类,只要实现相应的方法,那么就可以被静态检查器认为是符合Protocol的。
    2. 不需要继承自具体父类。和上一条一样,即使一个类没有任何父类(除了object类),它依旧可以生成同名的方法,以实现和父类方法相同的调用接口。这样在语义逻辑上,类的定义完全看不出和其他类有何种关系。完全可以是一种松散的组织结构,任何两个类之间都没继承关系。
  3. 破坏多态:任何一个入参出参,天然不限制类型。这使得要求父类型的参数处,传入子类型显得没有意义,依旧是因为任何类型都能动态修改满足要求。

破坏了设计模式

经典的模式诸如工厂模式,抽象工厂,访问者模式,都严重依赖于继承和多态的性质。但是在python的设计中,其动态能力使得设计模式形同虚设。 大家常见的库中使用设计模式的有transformers库,其中的from_pretrained系列则是工厂模式,通过字符串名称确定了具体的构造器得到具体的子类。而工厂构造器的输出类型是一个所有模型的基类。

安全性问题

Python在代码层面一般不直接管理指针,所以指针越界,野指针,悬空指针等问题一般不存在。而gc机制也能自动处理垃圾回收使得编码过程不必关注这类安全性问题。但与之相对的,Python也有自己的安全性问题。以往非托管形式的代码的攻击难度较大,注入代码想要稳定执行需要避免破坏原来的结构导致程序直接崩溃(段错误)。 Python却可以直接注入任何代码修改原本的逻辑,并且由于不是在code段固定的内容,攻击时候也无需有额外考虑。运行时可以手动修改globals() locals()内容,亦有一定风险。 另一个危险则是类型不匹配导致的代码执行问题,因为只有在运行时才确定类型,无法提前做出保证,可能会产生类型错误的异常,造成程序崩溃。

总结

我出身于C++。但是近年来一直在用python编程。而且python的市场占有率已经多年第一,且遥遥领先。这和其灵活性分不开关系。对于一个面向大众的编程语言,这样的特性是必要的。即使以上说了诸多python的不严谨之处,但是对于程序员依旧可以选择严谨的面向对象写法。所以,程序的优劣不在于语言怎么样,而在于程序员本身。程序员有责任写出易于维护,清晰,规范的代码~

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@KuRRe8
Copy link
Author

KuRRe8 commented May 8, 2025

返回顶部

有见解,有问题,或者单纯想盖楼灌水,都可以在这里发表!

因为文档比较多,有时候渲染不出来ipynb是浏览器性能的问题,刷新即可

或者git clone到本地来阅读

ChatGPT Image May 9, 2025, 04_45_04 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment