玩转python:通俗易懂掌握高级数据结构-collections模块之UserDict

news2025/3/18 21:59:46
引言

UserDict是Python中collections模块提供的一个强大工具,它是dict的封装类,允许用户自定义字典的行为。通过继承UserDict,开发者可以轻松扩展字典的功能,实现自定义的字典逻辑。本文将详细介绍UserDict的关键用法和特性,并通过10个丰富的案例帮助读者掌握其应用。


关键用法和特性表格
特性/方法描述
自定义字典行为继承UserDict可以自定义字典的行为,如添加、删除、查找等。
封装原始字典UserDict内部封装了一个字典对象,可以通过data属性访问。
初始化使用UserDict(initialdata)创建,支持传入初始字典。
data返回内部封装的字典对象。
支持所有字典操作支持所有字典操作,如键值访问、更新、删除等。
扩展功能可以通过重写方法实现自定义功能,如验证键值、记录操作日志等。

1. UserDict的概念

UserDictcollections模块中的一个类,它是dict的封装类。它的主要特点是:

  • 自定义字典行为:通过继承UserDict,可以自定义字典的行为。
  • 封装原始字典UserDict内部封装了一个字典对象,可以通过data属性访问。
  • 高效性能:与普通字典相比,UserDict在自定义功能的同时性能依然高效。

2. UserDict的用法

2.1 创建UserDict
from collections import UserDict

# 创建一个空的UserDict
ud = UserDict()
print(ud)  # 输出: {}

# 从字典创建UserDict
ud = UserDict({'a': 1, 'b': 2})
print(ud)  # 输出: {'a': 1, 'b': 2}
2.2 访问键值对
# 访问键值对
print(ud['a'])  # 输出: 1
print(ud['b'])  # 输出: 2
2.3 修改键值对
# 修改键值对
ud['a'] = 10
print(ud)  # 输出: {'a': 10, 'b': 2}

3. UserDict的常见方法

3.1 data:访问内部字典
# 访问内部字典
print(ud.data)  # 输出: {'a': 10, 'b': 2}
3.2 自定义字典行为
# 自定义字典行为
class MyDict(UserDict):
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise TypeError("Key must be a string")
        super().__setitem__(key, value)

md = MyDict({'a': 1, 'b': 2})
md['c'] = 3  # 正常
md[1] = 'a'  # 报错: TypeError

4. UserDict的10个应用案例

案例1:验证键类型

场景:自定义一个字典,确保所有键都是字符串。

class StrKeyDict(UserDict):
    def __setitem__(self, key, value):
        if not isinstance(key, str):
            raise TypeError("Key must be a string")
        super().__setitem__(key, value)

# 使用StrKeyDict
skd = StrKeyDict({'a': 1, 'b': 2})
skd['c'] = 3  # 正常
skd[1] = 'a'  # 报错: TypeError
案例2:记录操作日志

场景:自定义一个字典,记录所有添加和删除操作。

class LoggingDict(UserDict):
    def __setitem__(self, key, value):
        print(f"添加键值对: {key} -> {value}")
        super().__setitem__(key, value)

    def __delitem__(self, key):
        print(f"删除键: {key}")
        super().__delitem__(key)

# 使用LoggingDict
ld = LoggingDict({'a': 1, 'b': 2})
ld['c'] = 3  # 输出: 添加键值对: c -> 3
del ld['a']  # 输出: 删除键: a
案例3:限制字典大小

场景:自定义一个字典,限制其最大大小。

class LimitedDict(UserDict):
    def __init__(self, maxsize, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.maxsize = maxsize

    def __setitem__(self, key, value):
        if len(self) >= self.maxsize:
            self.popitem()
        super().__setitem__(key, value)

# 使用LimitedDict
ld = LimitedDict(2, {'a': 1, 'b': 2})
ld['c'] = 3  # 字典变为 {'b': 2, 'c': 3}
案例4:实现默认值字典

场景:自定义一个字典,访问不存在的键时返回默认值。

class DefaultValueDict(UserDict):
    def __init__(self, default_value, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.default_value = default_value

    def __missing__(self, key):
        return self.default_value

# 使用DefaultValueDict
dvd = DefaultValueDict(0, {'a': 1, 'b': 2})
print(dvd['a'])  # 输出: 1
print(dvd['c'])  # 输出: 0(默认值)
案例5:实现大小写不敏感字典

场景:自定义一个字典,键的大小写不敏感。

class CaseInsensitiveDict(UserDict):
    def __setitem__(self, key, value):
        super().__setitem__(key.lower(), value)

    def __getitem__(self, key):
        return super().__getitem__(key.lower())

# 使用CaseInsensitiveDict
cid = CaseInsensitiveDict({'a': 1, 'B': 2})
print(cid['A'])  # 输出: 1
print(cid['b'])  # 输出: 2
案例6:实现只读字典

场景:自定义一个字典,禁止修改和删除操作。

class ReadOnlyDict(UserDict):
    def __setitem__(self, key, value):
        raise TypeError("字典是只读的,不能修改")

    def __delitem__(self, key):
        raise TypeError("字典是只读的,不能删除")

# 使用ReadOnlyDict
rod = ReadOnlyDict({'a': 1, 'b': 2})
print(rod['a'])  # 输出: 1
rod['c'] = 3  # 报错: TypeError
案例7:实现计数器字典

场景:自定义一个字典,统计每个键的访问次数。

class CountingDict(UserDict):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.count = {}

    def __getitem__(self, key):
        self.count[key] = self.count.get(key, 0) + 1
        return super().__getitem__(key)

# 使用CountingDict
cd = CountingDict({'a': 1, 'b': 2})
print(cd['a'])  # 输出: 1
print(cd['a'])  # 输出: 1
print(cd.count)  # 输出: {'a': 2}
案例8:实现缓存字典

场景:自定义一个字典,缓存计算结果。

class CachingDict(UserDict):
    def __init__(self, func, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.func = func

    def __getitem__(self, key):
        if key not in self:
            self[key] = self.func(key)
        return super().__getitem__(key)

# 使用CachingDict
def expensive_computation(key):
    return key.upper()

cd = CachingDict(expensive_computation)
print(cd['a'])  # 输出: A
print(cd['a'])  # 输出: A(从缓存中获取)
案例9:实现优先级字典

场景:自定义一个字典,按优先级插入键值对。

class PriorityDict(UserDict):
    def insert_priority(self, key, value, priority):
        for k, (p, _) in self.items():
            if priority > p:
                self[key] = (priority, value)
                return
        self[key] = (priority, value)

# 使用PriorityDict
pd = PriorityDict()
pd.insert_priority('task1', 'low', 1)
pd.insert_priority('task2', 'high', 3)
pd.insert_priority('task3', 'medium', 2)
print(pd)  # 输出: {'task2': (3, 'high'), 'task3': (2, 'medium'), 'task1': (1, 'low')}
案例10:实现去重字典

场景:自定义一个字典,确保值不重复。

class UniqueValueDict(UserDict):
    def __setitem__(self, key, value):
        if value in self.values():
            raise ValueError("值已存在")
        super().__setitem__(key, value)

# 使用UniqueValueDict
uvd = UniqueValueDict({'a': 1, 'b': 2})
uvd['c'] = 3  # 正常
uvd['d'] = 2  # 报错: ValueError

总结

UserDict是Python中一个非常实用的工具,能够帮助开发者轻松扩展字典的功能。通过本文的详细讲解和10个实际案例,大家可以快速掌握UserDict的使用方法,并在实际项目中灵活应用。无论是验证键类型、记录操作日志,还是实现缓存和去重字典,UserDict都能轻松应对!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2317438.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ollama docker设置模型常驻显存

参考: https://github.com/ollama/ollama/issues/5272 https://deepseek.csdn.net/67cfd7c93b685529b708fdee.html 通过-e传入环境变量,ollama运行: docker run -d --gpusall -e OLLAMA_KEEP_ALIVE-1 -v ollama:/root/.ollama -p 11434:114…

无再暴露源站!群联AI云防护IP隐匿方案+防绕过实战

一、IP隐藏的核心原理 群联AI云防护通过三层架构实现源站IP深度隐藏: 流量入口层:用户访问域名解析至高防CNAME节点(如ai-protect.example.com)智能调度层:基于AI模型动态分配清洗节点,实时更新节点IP池回…

【深度学习|目标检测】YOLO系列anchor-based原理详解

YOLO之anchor-based 一、关于anchors的设置二、网络如何利用anchor来训练关于register_buffer训练阶段的anchor使用推理阶段的anchor使用 三、训练时的正负样本匹配静态策略:跨分支采样跨anchor采样跨grid采样 动态策略 总结起来其实就是:基于anchor-bas…

Linux 入门:权限的认识和学习

目录 一.shell命令以及运行原理 二.Linux权限的概念 1.Linux下两种用户 cannot open directory .: Permission denied 问题 2.Linux权限管理 1).是什么 2).为什么(权限角色目标权限属性) 3).文件访问者的分类(角色) 4).文…

搭建opensbi+kernel+rootfs及基本设备驱动开发流程

目录 一.编译qemu 运行opensbikernelrootfs 1.编译qemu-9.1.1 2.安装riscv64编译器 3. 编译opensbi 4.编译kernel 5.编译rootfs 设备驱动开发流程 1.安装 RISC-V 交叉编译工具链 2.驱动开发准备 3.编写简易中断控制器驱动(PLIC)​ 4.配置内核…

QT非UI设计器生成界面的国际化

目的 UI设计器生成界面的国际化,比较容易实现些,因为有现成的函数可以调用,基本过程如下: void MainWindow::on_actLang_CN_triggered() {//中文界面qApp->removeTranslator(trans);delete trans;transnew QTranslator;trans…

python | 输入日期,判断这一天是这一年的第几天

题目: 使用 python 编程,实现输入日期,判断这一天是这一年的第几天? 具体实现代码如下: import datetime year input(请输入年份:) month input(请输入月份:) day input(请输入天:) date…

单片机开发资源分析的实战——以STM32F103C8T6为例子的单片机资源分析

目录 第一点:为什么叫STM32F103C8T6 从资源手册拿到我们的对STM32F103C8T6的资源描述 第二件事情,关心我们的GPIO引脚输出 第三件事情:去找对应外设的说明部分 前言 本文章隶属于项目: Charliechen114514/BetterATK: This is…

Maven | 站在初学者的角度配置

目录 Maven 是什么 概述 常见错误 创建错误代码示例 正确代码示例 Maven 的下载 Maven 依赖源 Maven 环境 环境变量 CMD测试 Maven 文件配置 本地仓库 远程仓库 Maven 工程创建 IDEA配置Maven IDEA Maven插件 Maven 是什么 概述 Maven是一个项目管理和构建自…

【css酷炫效果】纯CSS实现3D翻转卡片动画

【css酷炫效果】纯CSS实现3D翻转卡片动画 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板,链接放在这里:https://download.csdn.net/download/u011561335/90490472 缘 创作随缘,不定时更新。 创作背景 刚看到csdn出活动了&am…

并发编程面试题二

1、java线程常见的基本状态有哪些,这些状态分别是做什么的 (1)创建(New):new Thread(),生成线程对象。 (2)就绪(Runnable):当调用线程对象的sta…

Spring Cloud Stream - 构建高可靠消息驱动与事件溯源架构

一、引言 在分布式系统中,传统的 REST 调用模式往往导致耦合,难以满足高并发和异步解耦的需求。消息驱动架构(EDA, Event-Driven Architecture)通过异步通信、事件溯源等模式,提高了系统的扩展性与可观测性。 作为 S…

突破连接边界!O9201PM Wi-Fi 6 + 蓝牙 5.4 模块重新定义笔记本无线体验

在当今数字化时代,笔记本电脑已成为人们工作、学习和娱乐的必备工具。而无线连接技术,作为笔记本电脑与外界交互的关键桥梁,其性能的优劣直接关乎用户体验的好坏。当下,笔记本电脑无线连接领域存在诸多痛点,严重影响着…

Python----计算机视觉处理(Opencv:图像颜色替换)

一、开运算 开运算就是对图像先进行腐蚀操作, 然后进行膨胀操作。开运算可以去除二值化图中的小的噪点,并分离相连的物体。 其主要目的就是消除那些小白点 在开运算组件中,有一个叫做kernel的参数,指的是核的大小,通常…

一周学会Flask3 Python Web开发-SQLAlchemy查询所有数据操作-班级模块

锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们来新建一个的蓝图模块-班级模块,后面可以和学生模块,实现一对多的数据库操作。 blueprint下新建g…

Matlab 风力发电机磁悬浮轴承模型pid控制

1、内容简介 略 Matlab 174-风力发电机磁悬浮轴承模型pid控制 可以交流、咨询、答疑 2、内容说明 磁悬浮轴承具有无接触、无摩擦、高速度、高精度、能耗低、不需要需润滑无油污染、可靠性高、寿命长和密封等一系列显著的优点。将磁悬浮技术应用于风力发电机中可以降低风机切入…

FPGA中级项目1——IP核(ROM 与 RAM)

FPGA中级项目1——IP核(ROM 与 RAM) IP核简介 在 FPGA(现场可编程门阵列)设计中,IP 核(Intellectual Property Core,知识产权核)是预先设计好的、可重用的电路模块,用于实…

Matlab 基于专家pid控制的时滞系统

1、内容简介 Matlab 185-基于专家pid控制的时滞系统 可以交流、咨询、答疑 2、内容说明 略 在处理时滞系统(Time Delay Systems)时,使用传统的PID控制可能会面临挑战,因为时滞会导致系统的不稳定或性能下降。专家PID控制通过结…

Unity 笔记:在EditorWindow中绘制 Sorting Layer

在Unity开发过程中,可能会对旧资源进行批量修改,一个个手动修改费人费事,所以催生出了一堆批量工具。 分享一下在此过程中绘制 Sorting Layer 面板的代码脚本。 示意图: 在 EditorGUI 和 EditorGUILayer 中内置了 SortingLayerF…

2024浙江大学计算机考研上机真题

2024浙江大学计算机考研上机真题 2024浙江大学计算机考研复试上机真题 2024浙江大学计算机考研机试真题 2024浙江大学计算机考研复试机试真题 历年浙江大学计算机复试上机真题 历年浙江大学计算机复试机试真题 2024浙江大学计算机复试上机真题 2024浙江大学计算机复试机试真题 …