当前位置: 首页 > news >正文

Python 的几个重要的相关概念

1. EAFP vs LBYL

这是 Python 的核心编程风格,与鸭子类型密切相关。

EAFP (Easier to Ask for Forgiveness than Permission)

"请求原谅比获得许可更容易" - 直接尝试操作,如果出错就处理异常。

# EAFP 风格 - Pythonic
def get_length(obj):try:return len(obj)except TypeError:return "对象没有长度"print(get_length([1, 2, 3]))    # 3
print(get_length(42))           # 对象没有长度

LBYL (Look Before You Leap)

"三思而后行" - 先检查再操作。

# LBYL 风格
def get_length(obj):if hasattr(obj, '__len__'):return len(obj)else:return "对象没有长度"

EAFP 与鸭子类型的关系:都体现了"先尝试,有问题再处理"的 Python 哲学。


2. 协议

协议是鸭子类型的正式化表达,通过 typing.Protocol 实现。

from typing import Protocol, runtime_checkable@runtime_checkable
class SupportsAdd(Protocol):def __add__(self, other): ...class Vector:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):return Vector(self.x + other.x, self.y + other.y)class StringWrapper:def __init__(self, value):self.value = valuedef __add__(self, other):return StringWrapper(self.value + other.value)def add_objects(a, b: SupportsAdd) -> SupportsAdd:"""接受任何实现了 __add__ 的对象"""return a + b# 使用
v1 = Vector(1, 2)
v2 = Vector(3, 4)
result = add_objects(v1, v2)  # 正常工作s1 = StringWrapper("hello")
s2 = StringWrapper(" world")
result = add_objects(s1, s2)  # 也正常工作print(isinstance(v1, SupportsAdd))  # True - 运行时检查
print(isinstance("hello", SupportsAdd))  # False - 字符串没有 __add__ 方法

3. 结构化类型

关注对象的结构(有哪些方法/属性)而非继承关系。

from typing import TypedDictclass PersonDetails(TypedDict):name: strage: intdef process_person(data: PersonDetails) -> str:return f"{data['name']} is {data['age']} years old"# 任何具有 'name' 和 'age' 键的字典都可以使用
person1 = {'name': 'Alice', 'age': 25}
person2 = {'name': 'Bob', 'age': 30, 'city': 'NY'}  # 额外的属性也可以print(process_person(person1))  # Alice is 25 years old
print(process_person(person2))  # Bob is 30 years old

4. 猴子补丁

在运行时动态修改类或模块。

class Person:def __init__(self, name):self.name = namedef greet(self):return f"Hello, I'm {self.name}"# 猴子补丁:运行时添加新方法
def introduce(self):return f"My name is {self.name}"Person.introduce = introduceperson = Person("Alice")
print(person.greet())    # Hello, I'm Alice
print(person.introduce()) # My name is Alice - 运行时添加的方法

5. 混入类

通过多重继承提供可重用的功能。

class JSONSerializableMixin:def to_json(self):import jsonreturn json.dumps(self.__dict__)class XMLSerializableMixin:def to_xml(self):attrs = ''.join(f' {k}="{v}"' for k, v in self.__dict__.items())return f"<object{attrs}/>"class Person(JSONSerializableMixin, XMLSerializableMixin):def __init__(self, name, age):self.name = nameself.age = ageclass Product(JSONSerializableMixin):def __init__(self, name, price):self.name = nameself.price = price# 使用
person = Person("Alice", 25)
print(person.to_json())  # {"name": "Alice", "age": 25}
print(person.to_xml())   # <object name="Alice" age="25"/>product = Product("Book", 29.99)
print(product.to_json()) # {"name": "Book", "price": 29.99}
# product.to_xml()  # 会报错,因为没有混入 XMLSerializableMixin

6. 抽象基类

虽然与鸭子类型相反(强调显式继承),但 ABC 可以用来定义"协议"。

from abc import ABC, abstractmethod
from collections.abc import Sized, Iterableclass Drawable(ABC):@abstractmethoddef draw(self):passclass Circle(Drawable):def draw(self):return "绘制圆形"class Square(Drawable):def draw(self):return "绘制正方形"def render_all(drawables):for obj in drawables:if isinstance(obj, Drawable):  # 显式检查print(obj.draw())# 使用内置的 ABC
def process_sized_objects(obj: Sized):"""接受任何有 __len__ 的对象"""return f"长度: {len(obj)}"print(process_sized_objects([1, 2, 3]))    # 长度: 3
print(process_sized_objects({"a": 1})))     # 长度: 1

7. 上下文管理器协议

任何实现了 __enter__ 和 __exit__ 方法的对象都可以用于 with 语句。

class Timer:def __init__(self, name):self.name = namedef __enter__(self):import timeself.start = time.time()print(f"开始 {self.name}")return selfdef __exit__(self, exc_type, exc_val, exc_tb):import timeelapsed = time.time() - self.startprint(f"结束 {self.name}, 耗时: {elapsed:.2f}秒")# 使用
with Timer("计算任务"):sum(range(1000000))# 输出:
# 开始 计算任务
# 结束 计算任务, 耗时: 0.05秒

8. 可调用对象协议

任何实现了 __call__ 方法的对象都可以像函数一样调用。

class Multiplier:def __init__(self, factor):self.factor = factordef __call__(self, x):return x * self.factorclass Greeter:def __call__(self, name):return f"Hello, {name}!"# 使用
double = Multiplier(2)
greet = Greeter()print(double(5))      # 10 - 像函数一样调用
print(greet("Alice")) # Hello, Alice! - 像函数一样调用# 可以传递给期望函数的参数
numbers = [1, 2, 3, 4]
doubled = list(map(double, numbers))
print(doubled)  # [2, 4, 6, 8]

9. 描述符协议

控制属性访问的行为。

class ValidatedString:def __init__(self, min_length=0, max_length=100):self.min_length = min_lengthself.max_length = max_lengthdef __set_name__(self, owner, name):self.name = namedef __get__(self, obj, objtype=None):return obj.__dict__.get(self.name)def __set__(self, obj, value):if not isinstance(value, str):raise TypeError("必须是字符串")if not (self.min_length <= len(value) <= self.max_length):raise ValueError(f"长度必须在 {self.min_length} 到 {self.max_length} 之间")obj.__dict__[self.name] = valueclass Person:name = ValidatedString(1, 50)email = ValidatedString(5, 100)def __init__(self, name, email):self.name = nameself.email = email# 使用
person = Person("Alice", "alice@example.com")
print(person.name)  # Alicetry:person.name = ""  # 会抛出 ValueError
except ValueError as e:print(f"错误: {e}")

总结

这些概念都与鸭子类型共享相同的精神:

概念核心思想与鸭子类型的关系
EAFP先尝试,出错再处理编程风格的体现
协议正式化的鸭子类型类型系统的支持
结构化类型关注结构而非名称数据层面的鸭子类型
猴子补丁运行时修改行为动态性的极端体现
混入类通过组合提供功能代码复用的方式
上下文管理器通过方法实现协议特定协议的鸭子类型
可调用对象像函数一样使用对象调用协议的鸭子类型
描述符控制属性访问属性访问协议的鸭子类型

这些概念共同构成了 Python 的"动态类型系统",让 Python 代码既灵活又强大,鼓励基于行为而非类型的编程风格。

http://www.dtcms.com/a/605390.html

相关文章:

  • 零基础学AI大模型之Milvus核心:分区-分片-段结构全解+最佳实践
  • Spring AI Alibaba 自学习AI智能体实战:让AI越用越懂你
  • Springboot主配置文件
  • 家具电商网站建设一定要建设好网站才能备案吗
  • 医药建设网站wordpress 柚子皮下载
  • Java被裁后如何快速上岸?
  • 拥抱元宇宙:通过GoogleVR来了解VR到底是什么
  • 【UE5】- VR小技巧 :用PC处理代替频繁使用VR头显开发
  • 攻击者利用自定义GPT的SSRF漏洞窃取ChatGPT机密数据
  • 支付招聘网站套餐费用怎么做帐wordpress preg_replace 关键词 alt
  • GPT-5.1发布:深入解读与 GPT-5、GPT-4o 在性能与安全基准上的全面对比
  • 两台虚拟机搭建多机区块链网络
  • Vue.js栏目 - 目录一展
  • 网站采集怎么做莱芜金点子广告电子版2022最新
  • 2025 最硬核技术创新,重构 AI 感知与决策逻辑
  • flowable05外置表单和绘制流程图
  • UDP网络编程:从客户端封装到服务端绑定的深度实践
  • Arbess从初级到进阶(4) - 使用Arbess+GitLab实现React.js 项目自动化部署
  • 内网穿透技术
  • asp.net做织梦网站长沙商城网站开发
  • [免费]基于Python的深度学习豆瓣电影数据可视化+情感分析推荐系统(Flask+Vue+LSTM+scrapy)【论文+源码+SQL脚本】
  • SQL 分类
  • 微信小程序项目上传到git仓库(完整操作)
  • Vue 3响应式系统的底层机制:Proxy如何实现依赖追踪与自动更新?
  • 【MySQL】MySQL库的操作
  • 研发管理知识库(10)AWS云的核心DevOps工具介绍
  • PostgreSQL 备份导致的 Cache Pollution(缓存污染)
  • 拒绝繁杂,一款轻量,极致简洁的开源DevOps平台 - TikLab
  • 深入解析Flink会话窗口机制
  • 南京建设网站企业wordpress的伪静态