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

dict.setdefault() 用法

setdefault 是Python中字典的一个方法,用于在字典中查找指定键,如果键存在,则返回对应值(而不是指定的默认值);如果键不存在,则在字典中添加该键,并将其值设置为指定的默认值

dict.setdefault(key, default_value)

其中,key为要查找或添加的键,default_value为键不存在时设置的默认值(若省略,默认None)

d = {}
d.setdefault("list", []).append(1)
d.setdefault("list", []).append(2)
print(d)  # 输出:{"list": [1, 2]}
# 为字典d添加一个键'list',并将其值设置为一个空列表
# 使用列表的append方法向该列表中添加元素1和2

底层原理

Python中字典是一种无序的键值对集合,它的底层实现是通过拉链法实现的哈希表

  • 什么是哈希表?一种根据关键字直接访问内存位置的数据结构,通过哈希函数将关键字映射到对应的内存位置
  • 什么是拉链法(chaining)?每个哈希桶中存储一个链表, 哈希值相同的键值对会被插入到同一个链表中。当需要查找或插入一个键值对时,先计算出该键的哈希值,然后根据哈希值找到对应的哈希桶,再在该哈希桶对应的链表中查找或插入键值对
  • 什么是哈希桶(bucket)?是哈希表中存储元素的容器,是一个动态数组,每个元素都是一个链表,链表中的每个节点都是一个键值对
    • 哈希桶的大小通常是一个质数,这是为了保证哈希函数的均匀性和哈希表的性能。如果哈希桶比较小,会导致哈希冲突(hash collision)的概率增大,从而降低哈希表的性能;如果哈希桶比较大,会浪费内存空间
    • 哈希桶的大小是根据哈希表的负载因子(load factor)和哈希表中元素数量来计算的。同时是动态调整的,当哈希表中元素数量达到一定阈值时,会自动扩容哈希表,增加哈希桶的数量,在保证哈希函数均匀性和哈希表性能的同时,提高哈希表的存储容量

setdefault方法的底层实现步骤:

  1. 计算要查找或添加的键的哈希值,找到对应的哈希桶
  2. 遍历哈希桶对应的链表,查找是否有键与要查找或添加的键相同
  3. 如果找到了相同的键,则返回该键对应的值
  4. 如果没有找到相同的键,则在链表头部添加一个新的键值对,并将键的值设置为默认值,返回默认值作为该键的值

与 dict.get() 的区别

dict.get时:

  • 若get的键存在,则返回对应键的value,若不存在则返回设置的default的值,默认为None
  • 字典中的键值不会发生任何变化

dict.setdefault时:

  • 若setdefault的键存在,则返回对应键的value,若不存在则返回设置的default的值,默认为None
  • 同时,字典中会将该键及设置的默认值添加到字典中

例1:添加一个新键和默认值 

d = {"a": 1, "b": 2}
d.get("c", 3)
print(d)  # 输出:{'a': 1, 'b': 2}d = {"a": 1, "b": 2}
d.setdefault("c", 3)
print(d)  # 输出:{'a': 1, 'b': 2, 'c': 3}
# 字典d本来并没有键为'c'的元素,使用setdefault方法可以添加一个新的键'c'和默认值3

例2:修改已有键的默认值

d = {"a": 1, "b": 2}
d.get("a", 3)
print(d)  # 输出:{"a": 1, "b": 2}d = {"a": 1, "b": 2}
d.setdefault("a", 3)
print(d)  # 输出:{"a": 1, "b": 2}
# 字典d已经有键'a',使用setdefault方法仍然会返回键'a'对应的值1,而不会修改它的默认值

例3:可以省略默认值参数

d = {"a": 1, "b": 2}
d.get("c")
print(d)  # 输出:{"a": 1, "b": 2}d = {"a": 1, "b": 2}
d.setdefault("c")
print(d)  # 输出:{"a": 1, "b": 2, "c": None}
# 省略了默认值参数,此时默认值为None

案例

我有一个字典,为用户评分数据,其中大写字母代表用户user,小写字母代表物品item:

user_score_dict = {'A': {'a': 3.0, 'b':4.0, 'c':0.0, 'd':3.5, 'e':0.0},'B': {'a': 4.0, 'b':0.0, 'c':4.5, 'd':0.0, 'e':3.5},'C': {'a': 0.0, 'b':3.5, 'c':0.0, 'd':0.0, 'e':3.0},'D': {'a': 0.0, 'b':4.0, 'c':0.0, 'd':3.5, 'e':3.0},
}

基于用户评分数据,构建共现矩阵,代码如下:

  • 什么是共现矩阵?行和列都代表物品a~e,元素代表同时喜欢两个物品的用户数
  • 显然,共现矩阵对角线全为0,且为对称矩阵
item_user_count = dict()   # 每个物品有多少用户产生过行为
count = dict()   # 共现矩阵for user, item in user_score_dict.items():for i in item.keys():item_user_count.setdefault(i, 0)if user_score_dict[user][i] > 0.0:item_user_count[i] += 1for j in item.keys():count.setdefault(i, {}).setdefault(j, 0)if (user_score_dict[user][i] > 0.0and user_score_dict[user][j] > 0.0and i != j):count[i][j] += 1

结果如下:

item_user_count:  {'a': 2, 'b': 3, 'c': 1, 'd': 2, 'e': 3}
# a物品被A和B两个用户交互过,所以为2,以此类推count:  {'a': {'a': 0, 'b': 1, 'c': 1, 'd': 1, 'e': 1}, 'b': {'a': 1, 'b': 0, 'c': 0, 'd': 2, 'e': 2}, 'c': {'a': 1, 'b': 0, 'c': 0, 'd': 0, 'e': 1}, 'd': {'a': 1, 'b': 2, 'c': 0, 'd': 0, 'e': 1}, 'e': {'a': 1, 'b': 2, 'c': 1, 'd': 1, 'e': 0}}
# 同时喜欢b和d的用户为A和D,有2个,所以为2,且对称,以此类推

在此基础上,得到物品之间的相似度矩阵,代码如下:

itemSim = dict()
for i, related_items in count.items():itemSim.setdefault(i, {})for j, cuv in related_items.items():itemSim[i].setdefault(j, 0)itemSim[i][j] = cuv / item_user_count[i]   # 同时喜欢物品i和j的用户数 / 喜欢物品i的用户数# 该公式可以理解为:喜欢物品i的用户中,有多少比例的用户也喜欢物品j

此处也可以写为:

for i, related_items in count.items():for j, cuv in related_items.items():itemSim.setdefault(i, {}).setdefault(j, 0)itemSim[i][j] = cuv / item_user_count[i]

结果如下:

itemSim:  
{'a': {'a': 0.0, 'b': 0.5, 'c': 0.5, 'd': 0.5, 'e': 0.5}, 'b': {'a': 0.3333333333333333, 'b': 0.0, 'c': 0.0, 'd': 0.6666666666666666, 'e': 0.6666666666666666}, 'c': {'a': 1.0, 'b': 0.0, 'c': 0.0, 'd': 0.0, 'e': 1.0}, 'd': {'a': 0.5, 'b': 1.0, 'c': 0.0, 'd': 0.0, 'e': 0.5}, 'e': {'a': 0.3333333333333333, 'b': 0.6666666666666666, 'c': 0.3333333333333333, 'd': 0.3333333333333333, 'e': 0.0}}

参考

python 中的 setdefault 方法详解、底层原理和用法-CSDN博客

Python中dict.setdefault的用法-CSDN博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 部署林风社交论坛/社交论坛linfeng-community遇到问题集合
  • hCaptcha 图像识别 API 对接说明
  • 『功能项目』QFrameWorkBug关联Slot(插槽)【67】
  • 一种新的电子邮件攻击方式:AiTM
  • 发展低空经济,对地理信息技术提出了哪些要求
  • Unreal Engine 5 C++: Asset Batch Duplication插件编写02
  • 5.《DevOps》系列K8S部署CICD流水线之K8S通过Yaml部署GitLab
  • VSCode好用的插件推荐
  • 错误码与错误提示设计
  • YOLOv9改进,YOLOv9主干网络为FasterNet(全网独发手把手教学,助力涨点)
  • AUTOSAR_EXP_ARAComAPI的5章笔记(7)
  • 如何创建标准操作规程(SOP)[+模板]
  • 从规范到实现解读Windows平台如何播放RTSP流
  • Redisson实现分布式锁(看门狗机制)
  • 《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理
  • Brief introduction of how to 'Call, Apply and Bind'
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Java Agent 学习笔记
  • JavaScript中的对象个人分享
  • Java读取Properties文件的六种方法
  • js数组之filter
  • KMP算法及优化
  • PV统计优化设计
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • SAP云平台里Global Account和Sub Account的关系
  • 关于字符编码你应该知道的事情
  • 机器学习学习笔记一
  • 基于组件的设计工作流与界面抽象
  • 跨域
  • 码农张的Bug人生 - 见面之礼
  • 设计模式走一遍---观察者模式
  • 一个完整Java Web项目背后的密码
  • 宾利慕尚创始人典藏版国内首秀,2025年前实现全系车型电动化 | 2019上海车展 ...
  • 交换综合实验一
  • ​如何防止网络攻击?
  • #{}和${}的区别是什么 -- java面试
  • #VERDI# 关于如何查看FSM状态机的方法
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (5)STL算法之复制
  • (Forward) Music Player: From UI Proposal to Code
  • (ibm)Java 语言的 XPath API
  • (PHP)设置修改 Apache 文件根目录 (Document Root)(转帖)
  • (windows2012共享文件夹和防火墙设置
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (实测可用)(3)Git的使用——RT Thread Stdio添加的软件包,github与gitee冲突造成无法上传文件到gitee
  • ****三次握手和四次挥手
  • .mat 文件的加载与创建 矩阵变图像? ∈ Matlab 使用笔记
  • .net 7和core版 SignalR
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET HttpWebRequest、WebClient、HttpClient
  • .NET NPOI导出Excel详解
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET上SQLite的连接
  • @RequestBody的使用