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
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
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python 元编程教程\n",
"\n",
"欢迎来到 Python 元编程教程!元编程(Metaprogramming)是指编写能够创建或操作其他代码(甚至是自身)的代码。\n",
"Python 是一种动态语言,这为元编程提供了肥沃的土壤。元编程可以让你在运行时检查、修改甚至生成类、函数和模块。\n",
"\n",
"**为什么学习元编程?**\n",
"\n",
"1. **框架和库的构建**:许多流行的 Python 框架(如 Django, SQLAlchemy)都广泛使用元编程来实现 ORM、API 自动化、插件系统等。\n",
"2. **减少重复代码 (DRY - Don't Repeat Yourself)**:通过元编程自动生成相似的代码模式。\n",
"3. **增强代码的灵活性和可扩展性**:创建更通用的组件。\n",
"4. **深入理解 Python**:学习元编程能让你对 Python 的内部工作机制有更深刻的理解。\n",
"\n",
"**警告**:元编程是一把双刃剑。虽然强大,但过度或不当使用会使代码难以理解和维护。请谨慎使用,确保其带来的好处大于复杂性。\n",
"\n",
"**本教程将涵盖三个核心元编程概念:**\n",
"\n",
"1. **装饰器 (Decorators)** - 深入\n",
"2. **描述符 (Descriptors)**\n",
"3. **元类 (Metaclasses)**"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 装饰器 (Decorators) - 深入\n",
"\n",
"装饰器是一种语法糖,允许你包装(或“装饰”)函数或方法。被装饰的函数或方法会替换为装饰器返回的新函数或方法。\n",
"我们先回顾基础,然后深入一些高级用法。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.1 基础函数装饰器回顾"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import functools\n",
"import time\n",
"\n",
"def simple_decorator(func):\n",
" @functools.wraps(func) # 保留被装饰函数的元信息 (如 __name__, __doc__)\n",
" def wrapper(*args, **kwargs):\n",
" print(f\"Calling {func.__name__} with arguments: {args}, {kwargs}\")\n",
" result = func(*args, **kwargs)\n",
" print(f\"{func.__name__} returned: {result}\")\n",
" return result\n",
" return wrapper\n",
"\n",
"@simple_decorator\n",
"def greet(name):\n",
" \"\"\"A simple greeting function.\"\"\"\n",
" return f\"Hello, {name}!\"\n",
"\n",
"print(greet(\"Alice\"))\n",
"print(f\"Function name: {greet.__name__}\")\n",
"print(f\"Function docstring: {greet.__doc__}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"等价于:\n",
"```python\n",
"def greet(name):\n",
" return f\"Hello, {name}!\"\n",
"greet = simple_decorator(greet)\n",
"```\n",
"`@functools.wraps(func)` 非常重要,它能确保装饰后的函数 `wrapper` 继承被装饰函数 `func` 的名称、文档字符串、参数列表等元信息。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.2 带参数的装饰器\n",
"\n",
"如果装饰器本身需要参数,你需要再加一层函数嵌套。装饰器工厂函数返回实际的装饰器。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def repeat(num_times):\n",
" \"\"\"装饰器工厂:返回一个能将函数调用重复 num_times 次的装饰器。\"\"\"\n",
" def decorator_repeat(func):\n",
" @functools.wraps(func)\n",
" def wrapper_repeat(*args, **kwargs):\n",
" results = []\n",
" for _ in range(num_times):\n",
" result = func(*args, **kwargs)\n",
" results.append(result)\n",
" print(f\"Called {func.__name__} {num_times} times.\")\n",
" return results # 或者根据需求返回最后一个结果等\n",
" return wrapper_repeat\n",
" return decorator_repeat\n",
"\n",
"@repeat(num_times=3)\n",
"def say_whee():\n",
" print(\"Whee!\")\n",
" return \"Done Whee\"\n",
"\n",
"whee_results = say_whee()\n",
"print(f\"Whee results: {whee_results}\")\n",
"\n",
"# 等价于:\n",
"# def say_whee():\n",
"# print(\"Whee!\")\n",
"# return \"Done Whee\"\n",
"# say_whee = repeat(num_times=3)(say_whee)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.3 类装饰器\n",
"\n",
"装饰器不仅可以是函数,也可以是类。如果一个类实现了 `__call__` 方法,它的实例就可以像函数一样被调用。\n",
"当使用类作为装饰器时,被装饰的函数会作为构造函数的参数传入。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class CountCalls:\n",
" def __init__(self, func):\n",
" functools.update_wrapper(self, func) # 类似 wraps,但用于类装饰器\n",
" self.func = func\n",
" self.num_calls = 0\n",
"\n",
" def __call__(self, *args, **kwargs):\n",
" self.num_calls += 1\n",
" print(f\"Call {self.num_calls} of {self.func.__name__!r}\")\n",
" return self.func(*args, **kwargs)\n",
"\n",
"@CountCalls\n",
"def example_function():\n",
" print(\"Inside example_function\")\n",
"\n",
"example_function()\n",
"example_function()\n",
"example_function()\n",
"\n",
"print(f\"example_function was called {example_function.num_calls} times.\")\n",
"\n",
"# 注意:此时 example_function 实际上是 CountCalls 的一个实例\n",
"print(type(example_function))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1.4 装饰类\n",
"\n",
"装饰器不仅可以装饰函数,还可以装饰整个类。装饰器会接收类对象作为参数,并返回一个(通常是修改过的)类对象。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def add_greeting_method(cls):\n",
" \"\"\"一个类装饰器,给类添加一个 'greet' 方法。\"\"\"\n",
" def greet_method(self):\n",
" return f\"Hello from an instance of {cls.__name__}! I have attribute 'name': {getattr(self, 'name', 'N/A')}\"\n",
" \n",
" cls.greet = greet_method # 在类上直接添加方法\n",
" return cls\n",
"\n",
"@add_greeting_method\n",
"class MyClass:\n",
" def __init__(self, name):\n",
" self.name = name\n",
"\n",
"my_instance = MyClass(\"DecoratedInstance\")\n",
"print(my_instance.greet()) # 现在 MyClass 的实例有了 greet 方法\n",
"\n",
"hasattr(MyClass, 'greet') # True"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 描述符 (Descriptors)\n",
"\n",
"描述符是一个实现了特定协议的类,该协议由 `__get__`, `__set__`, 和 `__delete__` 三个特殊方法组成。当一个描述符实例作为另一个类(宿主类)的类属性时,对该属性的访问会被这三个方法拦截。\n",
"\n",
"描述符是 Python 中许多特性(如 `property`, `@staticmethod`, `@classmethod`,甚至方法本身)的底层实现机制。\n",
"\n",
"协议方法:\n",
"* `obj.__get__(self, instance, owner)`: 获取属性值。\n",
" * `instance`: 宿主类的实例,或者当通过类访问时为 `None`。\n",
" * `owner`: 宿主类本身。\n",
"* `obj.__set__(self, instance, value)`: 设置属性值。\n",
"* `obj.__delete__(self, instance)`: 删除属性。\n",
"\n",
"如果一个对象同时定义了 `__get__` 和 `__set__`,它被称为**数据描述符 (data descriptor)**。如果只定义了 `__get__`,它被称为**非数据描述符 (non-data descriptor)**。数据描述符的优先级高于实例字典中的同名属性。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"class VerboseAttribute:\n",
" \"\"\"一个简单的数据描述符,记录属性的获取和设置。\"\"\"\n",
" def __init__(self, name):\n",
" self.name = name # 通常描述符会存储它要管理的属性的名称\n",
"\n",
" def __get__(self, instance, owner):\n",
" if instance is None: # 通过类访问\n",
" print(f\"Accessing {self.name} attribute from class {owner.__name__}\")\n",
" return self # 返回描述符实例本身\n",
" print(f\"Getting {self.name} from instance {instance}\")\n",
" # 通常值存储在实例的 __dict__ 中,使用一个不易冲突的名称\n",
" # 例如,如果 self.name 是 'x',可以存储为 '_x'\n",
" # 为简单起见,我们这里假设它直接存在或需要特殊处理\n",
" return instance.__dict__.get(f'_{self.name}', None)\n",
"\n",
" def __set__(self, instance, value):\n",
" print(f\"Setting {self.name} on instance {instance} to {value!r}\")\n",
" instance.__dict__[f'_{self.name}'] = value\n",
"\n",
" def __delete__(self, instance):\n",
" print(f\"Deleting {self.name} from instance {instance}\")\n",
" if f'_{self.name}' in instance.__dict__:\n",
" del instance.__dict__[f'_{self.name}']\n",
" else:\n",
" print(f\"Attribute _{self.name} not found on instance for deletion.\")\n",
"\n",
"class MyDescribedClass:\n",
" attr1 = VerboseAttribute(\"attr1\") # attr1 是 VerboseAttribute 的一个实例\n",
" \n",
" def __init__(self, initial_value):\n",
" self.attr1 = initial_value # 这会触发 VerboseAttribute.__set__\n",
"\n",
"print(\"--- Creating instance ---\")\n",
"obj = MyDescribedClass(10)\n",
"print(\"--- Accessing attribute ---\")\n",
"print(f\"Value: {obj.attr1}\") # 触发 __get__\n",
"print(\"--- Setting attribute ---\")\n",
"obj.attr1 = 20 # 触发 __set__\n",
"print(f\"New Value: {obj.attr1}\")\n",
"\n",
"print(\"--- Accessing via class ---\")\n",
"print(MyDescribedClass.attr1) # 触发 __get__,但 instance 为 None\n",
"\n",
"print(\"--- Deleting attribute ---\")\n",
"del obj.attr1 # 触发 __delete__\n",
"print(f\"Value after delete: {obj.attr1}\")\n",
"\n",
"print(\"--- Instance dictionary ---\")\n",
"print(obj.__dict__) # 注意属性值存储在 _attr1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2.1 `property()` 是一个描述符\n",
"\n",
"内置的 `property()` 函数就是使用描述符协议实现的。当你这样做:\n",
"```python\n",
"class C:\n",
" @property\n",
" def x(self):\n",
" return self._x\n",
" @x.setter\n",
" def x(self, value):\n",
" self._x = value\n",
"```\n",
"实际上 `x` 成为了一个 `property` 对象(一个描述符),它内部管理了 getter, setter 和 deleter 函数。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 元类 (Metaclasses)\n",
"\n",
"元类是“类的类”。就像类是创建对象的蓝图一样,元类是创建类的蓝图。\n",
"在 Python 中,`type` 是大多数内置类的元类,也是用户自定义类的默认元类。\n",
"\n",
"你可以通过指定类的 `metaclass` 关键字参数,或者通过继承一个具有特定元类的类,来使用自定义元类。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.1 `type` 作为元类\n",
"\n",
"`type` 不仅能告诉你对象的类型 (`type(obj)`),它也能动态地创建类。调用 `type` 时有三种形式:\n",
"1. `type(object)` -> 返回对象的类型\n",
"2. `type(name, bases, dict)` -> 创建并返回一个新的类对象。\n",
" * `name`: 类名 (字符串)\n",
" * `bases`: 父类的元组\n",
" * `dict`: 包含类属性和方法的字典"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 动态创建类\n",
"def dynamic_method(self):\n",
" return f\"I am a dynamic method from {self.name}\"\n",
"\n",
"DynamicClass = type(\n",
" 'DynamicClass', # 类名\n",
" (object,), # 父类 (这里是 object)\n",
" { # 属性和方法字典\n",
" 'name': 'MyDynamicInstance',\n",
" 'my_method': dynamic_method,\n",
" '__init__': lambda self, name: setattr(self, 'name', name) \n",
" }\n",
")\n",
"\n",
"dyn_obj = DynamicClass(\"TestDynamic\")\n",
"print(dyn_obj.name)\n",
"print(dyn_obj.my_method())\n",
"print(type(dyn_obj))\n",
"print(type(DynamicClass)) # <class 'type'>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.2 自定义元类\n",
"\n",
"自定义元类通常继承自 `type`。它们可以覆盖 `__new__` 和 `__init__` 方法来定制类的创建过程。\n",
"\n",
"* `Meta.__new__(mcs, name, bases, dct)`: 在类对象被创建之前调用。它必须返回新的类对象。\n",
" * `mcs`: 元类本身。\n",
" * `name`: 要创建的类的名称。\n",
" * `bases`: 父类的元组。\n",
" * `dct`: 包含类属性和方法的字典。\n",
"* `Meta.__init__(cls, name, bases, dct)`: 在类对象通过 `__new__` 创建之后调用,用于进一步初始化类。\n",
" * `cls`: 新创建的类对象。\n",
"\n",
"一个常见的用例是自动注册类(例如插件系统)或在类创建时强制执行某些编码约定。"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# 示例:一个确保所有类属性名都是大写的元类\n",
"class UpperAttrMetaclass(type):\n",
" def __new__(mcs, name, bases, dct):\n",
" print(f\"UpperAttrMetaclass.__new__ called for class '{name}'\")\n",
" print(f\" Original dct: {dct}\")\n",
" \n",
" uppercase_attrs = {}\n",
" for attr_name, attr_val in dct.items():\n",
" if not attr_name.startswith('__'): # 不修改特殊方法名\n",
" uppercase_attrs[attr_name.upper()] = attr_val\n",
" else:\n",
" uppercase_attrs[attr_name] = attr_val\n",
" \n",
" print(f\" Modified dct: {uppercase_attrs}\")\n",
" # 调用 type.__new__ 来实际创建类\n",
" new_class = super().__new__(mcs, name, bases, uppercase_attrs)\n",
" return new_class\n",
"\n",
" def __init__(cls, name, bases, dct):\n",
" print(f\"UpperAttrMetaclass.__init__ called for class '{name}'\")\n",
" print(f\" Class attributes after __new__: {vars(cls)}\")\n",
" super().__init__(name, bases, dct) # dct 这里是修改后的 dct\n",
"\n",
"\n",
"# 使用元类\n",
"class MyDataClass(metaclass=UpperAttrMetaclass):\n",
" field_one = 1\n",
" another_field = \"hello\"\n",
"\n",
" def normal_method(self):\n",
" return \"This is a normal method.\"\n",
"\n",
"print(\"--- After class definition ---\")\n",
"# 检查属性名是否已大写\n",
"print(f\"Has FIELD_ONE: {hasattr(MyDataClass, 'FIELD_ONE')}\") # True\n",
"print(f\"Has field_one: {hasattr(MyDataClass, 'field_one')}\") # False\n",
"print(f\"Has ANOTHER_FIELD: {hasattr(MyDataClass, 'ANOTHER_FIELD')}\") # True\n",
"print(f\"MyDataClass.FIELD_ONE = {MyDataClass.FIELD_ONE}\")\n",
"\n",
"instance = MyDataClass()\n",
"# 方法名通常不会被这种元类修改,因为它们通常在dct中是函数对象,\n",
"# 且元类修改的是键(属性名),而不是值(属性值)。\n",
"# 如果要修改方法名,需要在dct中进行更复杂的操作。\n",
"# print(instance.NORMAL_METHOD()) # 应该还是 normal_method,除非元类也改了它\n",
"print(instance.normal_method())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3.3 元类和继承\n",
"\n",
"如果一个类没有指定元类,它会继承其父类的元类。如果父类也没有指定元类,则默认为 `type`。\n",
"如果一个类有多个父类,且它们的元类不同,并且这些元类不是彼此的子类或父类,则会引发 `TypeError`(元类冲突)。Python 需要一个明确的元类继承链。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. 实际应用场景和思考\n",
"\n",
"**装饰器:**\n",
"* 日志记录 (Logging)\n",
"* 性能计时 (Timing)\n",
"* 缓存 (Caching, e.g., `functools.lru_cache`)\n",
"* 权限校验 (Authorization checks)\n",
"* 注册回调函数或插件\n",
"* 修改函数或方法的行为(如添加重试逻辑)\n",
"\n",
"**描述符:**\n",
"* 创建托管属性 (Managed attributes),如 `property`。\n",
"* 类型验证和数据转换。\n",
"* ORM 字段映射(如 Django 模型字段)。\n",
"* 实现 `@staticmethod` 和 `@classmethod`(它们是非数据描述符)。\n",
"* 延迟加载属性 (Lazy-loading attributes)。\n",
"\n",
"**元类:**\n",
"* API 创建和自动化(如自动生成符合特定接口的类)。\n",
"* 单例模式实现 (Singleton pattern)。\n",
"* ORM (Object-Relational Mappers) - 例如,Django 模型类使用元类来从字段定义创建数据库模式和查询 API。\n",
"* 插件注册和发现。\n",
"* 在类创建时强制执行编码标准或约定。\n",
"* 创建领域特定语言 (DSLs) 的一部分。\n",
"\n",
"**何时使用哪种?**\n",
"\n",
"* **装饰器**:当你需要修改或增强单个函数或类的行为,而不改变其核心功能或继承层次时,通常是最好的选择。它们相对简单易懂。\n",
"* **描述符**:当你需要更细致地控制类属性的访问、设置或删除行为时。它们通常用于创建可重用的属性管理逻辑。\n",
"* **元类**:当你需要控制整个类的创建过程,或者对多个类应用系统性的修改时。这是最强大但也最复杂的工具,应在其他方法不足以解决问题时才考虑。\n",
" “元类是99%的用户永远不需要担心的东西。如果你想知道是否需要它们,你就不需要(真正需要它们的人确切地知道他们需要它们,并且不寻求这样做的理由)。” —— Tim Peters (Python 核心开发者)\n",
"\n",
"## 总结\n",
"\n",
"元编程是 Python 中一个强大且富有表现力的方面。通过装饰器、描述符和元类,你可以编写出高度灵活和可定制的代码。\n",
"然而,重要的是要记住,代码的可读性和可维护性是首要的。只有在元编程能带来显著好处且不会过度复杂化代码时才使用它。\n",
"\n",
"多动手实践这些概念,并尝试阅读一些使用元编程的流行库的源代码,可以帮助你更好地理解它们的应用。"
]
}
],
"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.12"
}
},
"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.

对动态语言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