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

Python-鸭子类型

Python-鸭子类型

  • 前言
  • 鸭子类型应用场景
    • 1. 可迭代对象
    • 2. 容器对象
    • 3. 上下文管理器
    • 4. 可调用对象
    • 5. 文件类对象
    • 6. 序列类型
    • 7. 比较对象


前言

鸭子类型(Duck Typing)是一种编程风格,它不关注对象的具体类型,而是关注对象是否实现了特定的方法或协议

在 Python 中,鸭子类型是一种动态类型的风格,其核心思想是:“如果它走路像鸭子,叫起来像鸭子,那么它就是鸭子”


鸭子类型应用场景

1. 可迭代对象

是指可以被遍历(迭代)的对象
支持 for 循环和 iter()
字符串,列表,元组,字典,集合都是可迭代对象

方法
__iter__():返回一个迭代器(Iterator)对象。
__getitem__():支持通过整数索引访问元素(从 0 开始)

  • 循环遍历:for 循环自动将可迭代对象转换为迭代器
  • 解包操作:a, b = (1, 2)
  • 列表推导式:[x*2 for x in iterable]
  • 生成器表达式:(x*2 for x in iterable)
  • 内置函数:sum()、max()、min()、sorted() 等
for char in "hello":print(char, end=" ")  # h e l l o
for num in [1, 2, 3]:print(num, end=" ")   # 1 2 3
for key in {"a": 1, "b": 2}:print(key, end=" ")   # a b# 自定义可迭代类
class MyRange:def __init__(self, n):self.n = ndef __iter__(self):i = 0while i < self.n:yield i  # 使用生成器简化迭代器实现i += 1for i in MyRange(3):print(i, end=" ")  # 0 1 2

2. 容器对象

是一种可以包含其他对象的对象,它们实现了特定的方法来支持元素的存储、访问和管理

字符串、列表、集合都是容器

方法
__contains__(self, item):支持 in 操作符,检查元素是否存在
__len__(self):支持 len() 函数,返回容器长度

  • 成员检查:item in container
  • 长度计算:len(container)
  • 遍历:for item in container
# 判断子串
print("h" in "hello")       # True
print(1 in [1, 2, 3])       # True
print(1 in {1, 2, 3})       # True
print("key" in {"key": 1})  # True
# 查看字符串长度
print(len("abc "))  # 4(包含空格)# 自定义容器类
class MyList:def __init__(self, items):self.items = itemsdef __contains__(self, item):return item in self.items  # 委托给内置列表def __len__(self):return len(self.items)     # 委托给内置列表my_list = MyList([10, 20, 30])
print(20 in my_list)  # True
print(len(my_list))   # 3

3. 上下文管理器

用于管理资源的对象,确保资源在使用后被正确释放。上下文管理器通过 with 语句使用

方法
__enter__():进入上下文时调用,返回资源对象。
__exit__():退出上下文时调用,负责清理资源。

  • 资源管理:文件、网络连接、数据库连接等
  • 锁管理:线程锁、互斥锁
  • 状态恢复:临时修改全局状态,退出时恢复
  • 异常处理:集中处理特定代码块的异常
# 文件对象是上下文管理器
with open("test.txt", "w") as f:f.write("hello")  # 自动关闭文件# 线程锁也是上下文管理器
import threading
lock = threading.Lock()
with lock:# 自动获取和释放锁print("Locked")# 自定义上下文管理器
class Timer:def __enter__(self):import timeself.start = time.time()return self  # 返回值绑定到 as 后的变量def __exit__(self, exc_type, exc_val, exc_tb):import timeelapsed = time.time() - self.startprint(f"耗时: {elapsed:.2f}秒")with Timer():sum(i for i in range(10**7)) # 耗时: 0.47秒

4. 可调用对象

可以像函数一样被调用(使用 () 运算符)的对象或实体
函数、方法、类都是可调用对象

def add(a, b):return a + b
print(add(1, 2))  # 3class Adder:def __call__(self, a, b):return a + b
adder = Adder()
print(adder(3, 4))  # 7 (像函数一样调用实例)# 自定义可调用类
class Counter:def __init__(self):self.count = 0def __call__(self):self.count += 1return self.countcounter = Counter()
print(counter())  # 1
print(counter())  # 2

5. 文件类对象

是一种实现了文件接口的对象,也称为类文件对象流对象这类对象支持文件的基本操作(如读取、写入、关闭),但不一定对应物理文件,可能是内存中的数据、网络连接或其他数据源

方法

  • read(size=-1):读取指定字节数(默认读取全部)。
  • write(data):写入数据并返回写入的字节数。
  • close():关闭对象并释放资源。
  • seek(offset[, whence]):移动文件指针位置。
  • tell():返回当前文件指针位置。
# 标准库中的 StringIO 模拟文件操作
from io import StringIOf = StringIO()
f.write("hello")  # 写入内存
print(f.getvalue())  # hellof.seek(0)  # 移动文件指针到开头
print(f.read())  # hello# 自定义文件类
class LogFile:def __init__(self, filename):self.filename = filenamedef write(self, data):with open(self.filename, "a") as f:f.write(f"[LOG] {data}\n")def read(self):with open(self.filename, "r") as f:return f.read()log = LogFile("app.log")
log.write("User logged in")
print(log.read())  # [LOG] User logged in

6. 序列类型

是一种可迭代的容器,支持通过索引访问元素

  • 可变序列:列表 、字节数组
  • 不可变序列:字符串 、元组 、字节

通用操作

  • 索引访问:seq[index]
  • 切片:seq[start:stop:step]
  • 长度:len(seq)
  • 成员检查:x in seq
  • 重复:seq * n
  • 拼接:seq1 + seq2
  • 遍历:for x in seq
s = "hello"	   # 字符串
print(s[0])    # hlst = [1, 2, 3]	# 列表
print(lst[1])   # 2t = (4, 5, 6)  # 元组
print(t[2])    # 6# 自定义序列类
class MySequence:def __init__(self, data):self.data = datadef __getitem__(self, index):return self.data[index]  # 支持索引和切片seq = MySequence([10, 20, 30])
print(seq[0])       # 10
print(seq[1:])      # [20, 30]

7. 比较对象

是指实现了比较运算符(如 <、>、== 等)的对象。通过实现这些方法,对象可以用于排序、最大 / 最小值查找、条件判断等操作

常用的比较方法有:

  • __lt__(self, other):小于(<)
  • __le__(self, other):小于等于(<=)
  • __eq__(self, other):等于(==)
  • __ne__(self, other):不等于(!=)
  • __gt__(self, other):大于(>)
  • __ge__(self, other):大于等于(>=)
# 列表、元组、字符串都可以用 max()
print(max([3, 1, 4]))      # 4(列表)
print(max((5, 2, 9)))      # 9(元组)
print(max("hello"))        # 'o'(字符串)# 自定义类实现 __lt__() 也可以用 max()
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __lt__(self, other):return self.age < other.agepeople = [Person("Alice", 25), Person("Bob", 30)]
print(max(people).name)    # "Bob"(按年龄比较)
http://www.dtcms.com/a/348624.html

相关文章:

  • DBeaver连接SQL Server时添加驱动后仍提示找不到驱动的解决方法
  • 校园跑腿小程序源码 _ 跑腿便利店小程序 含搭建教程
  • 小程序全局状态管理:使用MobX进行跨组件数据共享详解(九)
  • c++基础知识入门
  • 【AI智能体】Dify 搭建业务单据差异核对助手实战详解
  • kubernetes中的认证和授权
  • Python 变量 (variables)、对象 (objects) 和引用 (references)
  • 第1章:量子涟漪
  • 双网卡并行访问:解决有线局域网与无线互联网共存时的路由冲突问题
  • 淘宝pc端首页做了哪些性能优化?
  • 大型 C/C++ 项目中 AI 助手(Cursor / Claude Code)日常操作清单与发散思路
  • MYSQL-表的约束(下)
  • 数据建模怎么做?一文讲清数据建模全流程
  • 设备管理与策略
  • UE5.5 C++ 增强输入 快速上手
  • nginx部署goaccess监控
  • JdbcTemplate和MyBatis的区别
  • 《支付回调状态异常的溯源与架构级修复》
  • 学习制作记录(选项UI以及存档系统)8.24
  • KVM虚拟化
  • Vue3 setup代替了vue2的哪些功能
  • 分布式事务的两种解决方案
  • MYSQL(DDL)
  • 前端 vs 后端请求:核心差异与实战对比
  • Qt——网络通信(UDP/TCP/HTTP)
  • 【Unity开发】Unity核心学习(二)
  • PAT 1081 Rational Sum
  • 【机器学习】8 Logistic regression
  • Power BI切片器自定义顺序
  • 智能油脂润滑系统:给设备一份 “私人定制” 的保养方案