从零打造属于你的Python容器类型:全流程图解+实战案例

在日常python开发中,内置的list、dict、set等容器类型极大地方便了我们的数据管理。但如果业务出现特殊需求,标准容器无法胜任怎么办?此时就需要自定义容器,既能像内置类型一样用,也能实现个性化行为!今天带你由浅入深地掌握Python"自定义容器"的全部方法和核心原理。


一、什么是自定义容器?

自定义容器指的是:实现特定"容器协议"的自定义类,对象能像list/dict一样支持索引、for循环、len()、in、切片等操作。

你可以实现:

  • 定长队列(缓存)
  • 有效期缓存字典
  • 只读/自定义校验的有序集合
  • 支持自定义索引的数据结构
  • "伪"list/"伪"dict等任意自定义数据行为

二、最基础的容器协议:__len____getitem____setitem__

示例:仿列表的自定义容器

python 复制代码
class MyList:
    def __init__(self, data=None):
        self._data = list(data) if data else []
        
    def __len__(self):
        return len(self._data)
    
    def __getitem__(self, idx):
        print(f"访问索引 {idx}")
        return self._data[idx]
    
    def __setitem__(self, idx, value):
        print(f"将{value}赋值到索引{idx}")
        self._data[idx] = value
    
    def append(self, value):
        self._data.append(value)
python 复制代码
ml = MyList([1, 2, 3])
print(len(ml))        # 3
print(ml[1])          # 访问索引 1  \n 2
ml[1] = 100           # 将100赋值到索引1
ml.append(200)
print(list(ml._data)) # [1, 100, 3, 200]

三、进阶协议:__iter__, __contains__和切片支持

  • __iter__ 让你的容器支持 for ... in ...
  • __contains__ 支持 in 判断
python 复制代码
class MyList:
    def __init__(self, data=None):
        self._data = list(data) if data else []
        
    def __len__(self):
        return len(self._data)
    
    def __getitem__(self, idx):
        print(f"访问索引 {idx}")
        return self._data[idx]
    
    def __setitem__(self, idx, value):
        print(f"将{value}赋值到索引{idx}")
        self._data[idx] = value
    
    def append(self, value):
        self._data.append(value)

    def __iter__(self):
        return iter(self._data)
    
    def __contains__(self, item):
        return item in self._data

ml = MyList([1, 2, 3])
print(len(ml))        # 3
print(ml[1])          # 访问索引 1  \n 2
ml[1] = 100           # 将100赋值到索引1
ml.append(200)
print(list(ml._data)) # [1, 100, 3, 200]

for i in ml:
    print(i)
print(100 in ml)  # True

支持切片

要支持切片,需要同时处理 indexslice

python 复制代码
   def __getitem__(self, idx):
        if isinstance(idx, slice):
            print(f"访问切片 {idx}")
            return MyList(self._data[idx])
        return self._data[idx]

四、实现字典型容器协议:__setitem____getitem____delitem__

自定义dict-like结构:

python 复制代码
class MyDict:
    def __init__(self):
        self._d = {}

    def __setitem__(self, key, value):
        self._d[key] = value

    def __getitem__(self, key):
        return self._d[key]

    def __delitem__(self, key):
        del self._d[key]

    def __contains__(self, key):
        return key in self._d

    def keys(self):
        return self._d.keys()

    def items(self):
        return self._d.items()
        
    def values(self):
        return self._d.values()

五、更高阶设计:自定义行为与约束

比如:只读容器、自动过滤、缓存等

python 复制代码
class ReadOnlyList:
    def __init__(self, data):
        self._data = list(data)
        
    def __getitem__(self, idx):
        return self._data[idx]
        
    def __len__(self):
        return len(self._data)
        
    def __setitem__(self, idx, value):
        raise NotImplementedError("只读容器!")
        
    def append(self, value):
        raise NotImplementedError("只读容器!")

六、魔法方法一览表(小抄)

魔法方法 作用
__len__ len(obj)
__getitem__ obj[key]
__setitem__ obj[key]=value
__delitem__ del obj[key]
__iter__ for x in obj
__contains__ x in obj
__reversed__ reversed(obj)

更多见Python数据模型官方文档


如果你喜欢这篇文章,欢迎点赞、收藏和转发,更多Python干货内容敬请关注!

相关推荐
神明不懂浪漫3 小时前
【第七章】Java中的常用类
java·开发语言·前端·经验分享·笔记
GuWenyue9 小时前
放弃云端API!一套React+WebGPU本地LLM方案,零数据上传、离线可用
前端·人工智能·前端框架
love530love10 小时前
OpenClaw Windows Companion 桌面客户端 连接 LM Studio 完整配置指南
人工智能·windows·python·openclaw
原则猫10 小时前
函数/变量提升
前端
独泪了无痕11 小时前
Vue3 Hooks使用实战解析
前端·vue.js
cui_ruicheng12 小时前
Python从入门到实战(十六):多进程编程
开发语言·python
shawxlee12 小时前
vue3在public下封装config.js自定义配置动态数据,可在打包后直接修改,方便后端部署及后续维护
前端·javascript·经验分享·vue·团队开发·js·项目优化
用户0595401744613 小时前
把记忆存储的回归测试从手工换成 Playwright + GitHub Actions,线上缺陷降低 80%
前端·css
触底反弹13 小时前
🚀 从 DOM0 级到 React 合成事件:前端事件监听的 20 年演进史
前端·react.js·面试
kyriewen13 小时前
我给前端项目的接口请求套了6层保护——才发现以前一直在裸奔
前端·javascript·面试