惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tor Project blog
AI
AI
S
Securelist
P
Privacy International News Feed
A
Arctic Wolf
T
Tenable Blog
C
Cisco Blogs
P
Proofpoint News Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
AWS News Blog
AWS News Blog
L
Lohrmann on Cybersecurity
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News and Events Feed by Topic
Know Your Adversary
Know Your Adversary
H
Heimdal Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cyberwarzone
Cyberwarzone
C
Cybersecurity and Infrastructure Security Agency CISA
S
Security Affairs
P
Palo Alto Networks Blog
K
Kaspersky official blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
博客园 - 叶小钗
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - Franky
SecWiki News
SecWiki News
IT之家
IT之家
G
GRAHAM CLULEY
酷 壳 – CoolShell
酷 壳 – CoolShell
C
CERT Recently Published Vulnerability Notes
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
LINUX DO - 最新话题
宝玉的分享
宝玉的分享
月光博客
月光博客
H
Help Net Security
P
Proofpoint News Feed
Cloudbric
Cloudbric
Latest news
Latest news
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Schneier on Security
Schneier on Security
Help Net Security
Help Net Security
Apple Machine Learning Research
Apple Machine Learning Research
Webroot Blog
Webroot Blog
B
Blog
量子位
J
Java Code Geeks
MyScale Blog
MyScale Blog

晚花行乐

马克卡尼在2026年达沃斯论坛上的讲话(阅读材料) | 晚花行乐 鸡娃如何用力才是恰到好处 | 晚花行乐 读万卷书,行万里路的辩证关系 | 晚花行乐 反对培训机构掐尖招生 | 晚花行乐 小泽和建国会谈最后10分钟全文(阅读材料) | 晚花行乐 来看看 DeepSeek 怎么鸡娃 | 晚花行乐 谈谈基本功 | 晚花行乐 惠普 ProDesk SFF PC 各系列参数对比 | 晚花行乐 解决瘦客户机上安装 Debian 12 启动失败问题 | 晚花行乐 意拾喻言:老外写的文言文 | 晚花行乐 笠翁对韵中的典故(十三元) | 晚花行乐 谈谈中考取消四小门 | 晚花行乐 亚马逊云科技产品免费试用攻略(3) - 对象存储服务 | 晚花行乐 在 Windows 10 LTSC 版本上安装 WSL2 | 晚花行乐 Debian 12 的常用配置项 | 晚花行乐 在 Debian 12 上安装 Nvidia 显卡驱动程序 | 晚花行乐 解决 Debian 12 关机失败问题 | 晚花行乐 解决 VS Code 自动更新版本后卡在连接界面 | 晚花行乐 观看巴黎奥运会有感 | 晚花行乐 在 Windows10 上安装惠普旧打印机驱动程序 | 晚花行乐 欢迎关注公众号:晚花行乐 | 晚花行乐 如何编写拼写检查器 | 晚花行乐 亚马逊云科技产品免费试用攻略(2) - 云服务器 | 晚花行乐 Pandas 中 axis 参数的理解(附实例) | 晚花行乐 我打算命个名,叫什么什么 Manager | 晚花行乐 上海武康路历史建筑一览 | 晚花行乐 Python 实现简单的数学表达式解析并处理 | 晚花行乐 观看马拉松的感悟 | 晚花行乐 Python 保存 Cookies 到文件并再次读取 | 晚花行乐 如何为 Hugo 静态网站添加评论功能 | 晚花行乐 Linux 共享打印服务 CUPS | 晚花行乐 如何为 Hugo 静态网站添加搜索功能 | 晚花行乐 解决 CSV 文件的第一列不能解析 | 晚花行乐 亚马逊云科技产品免费试用攻略(1) - 注册账户 | 晚花行乐 第二幕 Atma 的闲聊 | 晚花行乐 第二幕野蛮人的语音 | 晚花行乐 古入声和普通话平声对照 | 晚花行乐 第一幕的背景音乐 | 晚花行乐 第二幕亚马逊的语音 | 晚花行乐 第一幕的亚马逊的语音 | 晚花行乐 第一幕的野蛮人的语音 | 晚花行乐 MacOS 的彩蛋:Here's to the crazy ones | 晚花行乐 笠翁对韵的基本知识 | 晚花行乐 笠翁对韵中的典故(十二文) | 晚花行乐 笠翁对韵中的典故(十一真) | 晚花行乐 笠翁对韵中的典故(十灰) | 晚花行乐 杭州景点的楹联 | 晚花行乐 adb keycode 大全 | 晚花行乐 Scikit-learn 学习笔记(0)名词术语 | 晚花行乐 Scikit-learn 学习笔记(3)监督学习的例子 | 晚花行乐 SQLite 文档的学习笔记(1)长期支持计划 | 晚花行乐 SQLite 文档的学习笔记(2)测试方法 | 晚花行乐 笠翁对韵中的典故(九佳) | 晚花行乐 Ansible 如何检查一个程序的版本 | 晚花行乐 Ansible 如何检查一个文件夹是否存在 | 晚花行乐 pip 配置文件详解 | 晚花行乐 Ansible 如何检查一个URL是否正常 | 晚花行乐 Ansible 如何修改 iptables 规则 | 晚花行乐 Ansible 指定 playbook 运行的主机 | 晚花行乐 Ansible 如何清空文件夹 | 晚花行乐 Ansible 如何在本机执行命令 | 晚花行乐 笠翁对韵中的典故(八齐) | 晚花行乐 《伊索寓言》电子书 | 晚花行乐 菲伯尔钢琴伴奏:第二册 | 晚花行乐 Python 的 Keyword-Only Arguments 理解 | 晚花行乐 Python 的 函数参数处理机制 | 晚花行乐 瓦瑞夫在第一幕的闲聊 | 晚花行乐 瓦瑞夫在第一幕的任务提示 | 晚花行乐 第一幕的女巫语音 | 晚花行乐 《Fluent Python》 读书笔记:文本和字节序列 | 晚花行乐 第一幕的罗格语音 | 晚花行乐 第一幕的圣骑士语音 | 晚花行乐 第一幕的男巫语音 | 晚花行乐 第一幕的旁白 | 晚花行乐 第一幕的恶魔 | 晚花行乐 Python 中 Element Tree 的理解 | 晚花行乐 《Fluent Python》 读书笔记:字典和集合 | 晚花行乐 笠翁对韵中的典故(七虞) | 晚花行乐 笠翁对韵中的典故(五微) | 晚花行乐 笠翁对韵中的典故(六鱼) | 晚花行乐 笠翁对韵中的典故(一东) | 晚花行乐 笠翁对韵中的典故(二冬) | 晚花行乐 笠翁对韵中的典故(三江) | 晚花行乐 笠翁对韵中的典故(四支) | 晚花行乐 姜太公钓鱼 | 晚花行乐 武王建立周朝 | 晚花行乐 大禹治水 | 晚花行乐 尧舜让位 | 晚花行乐 黄帝战蚩尤 | 晚花行乐 上下五千年-精简版 | 晚花行乐 成功修复鼠标按键 | 晚花行乐 横向的Word文档怎么加页眉页脚 | 晚花行乐 商标通用化的故事:商标代替商品名 | 晚花行乐 搜索空文件夹的批处理程序 | 晚花行乐 Sn0wbreeze不能运行? | 晚花行乐 天线的驻波比 | 晚花行乐 天线参数:增益Gain | 晚花行乐 天线参数:方向图Radiation pattern | 晚花行乐 本拉登别墅的Google Earth坐标 | 晚花行乐 宜家帕克斯(PAX)衣柜的拼装过程 | 晚花行乐
Python 中 Defaultdict 的理解 | 晚花行乐
2022-01-14 · via 晚花行乐

collections.defaultdictdict.setdefault() 基础上发展而来的。

首先回顾 dict 类型最基本的取值方法:方括号 []

__getitem__() 方法

只要在自定义类里定义了这个方法,那么实例化出来的对象就拥有了 [] 取值的能力。

>>> class A:
...     def __getitem__(self, index):
...         return 'get item.'
...
>>> a=A()
>>> a[1]
'get item.'
>>> a['a']
'get item.'
>>>

如果是 dict 对象,用 [] 访问的 key 不存在,就会直接抛出 KeyError 异常。

>>> d={'a':1}
>>> d['b']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'b'
>>>

为了更优雅、更方便的处理这种异常场景,发展出了 get() 和 setdefault() 函数

get() 和 setdefault()

get() 提供了返回默认值功能

setdefault()get() 基础上,提供了将默认值(default)插回(set)字典的功能。这就是 setdefault 名称的由来。

>>> d={'a':1}
>>> d.setdefault('b',2)
2
>>> d
{'a': 1, 'b': 2}
>>>

但是每次调用 setdefault 函数,又不如 [] 提供的方式优雅,所以希望在 [] 取值方式中实现 setdefault 的功能。

# 想象中的样子
>>> d={'a':1}
>>> d['b']  # 不报错,直接创建默认值
>>> d
{'a': 1, 'b': 默认值}

于是需要改造 dict 类型,从 dict 派生出新类来实现这种需求。有下面两种方法:

  • 自己编写 dict 的派生类
  • 使用已有的 collections.defaultdict

这两种方法改造的关键点都是重(chóng)写 __missing__() 特殊方法。

__missing__() 方法

当基类 dict 发现给出的键不存在时,都会调用 __missing__() 方法。

虽然 dict 并没有定义这个方法,但是不妨碍它知道 __missing__() 这么个方法存在。

如果向子类的 __getitem__(key) 提供的 key 不存在的时候,就会自动的调用 __missing__()方法,同时不会抛出 KeyError 异常。

如果在 __missing__() 方法中设置一个动作,即向自己插入一个默认值,就实现了 这一节 最末希望实现的样子。

这里插入的默认值,是用一个工厂方法 default_factory 实现的,由 __missing__() 方法调用。

default_factory

default_factory 是一个 callable 对象,可以是一个函数或者类,当 __getitem__(key)key 不存在时,default_factory 会被 __missing__() 方法调用,用于生成那个不存在的 key 对应的默认值。

__missing__() 方法调用 default_factory 的时候,是不带任何参数的。

所以 default_factory 应该有以下这种行为:

>>> default_factory()
默认值
>>>

满足上述行为的,可以是以下这些对象:

  • 自定义的函数
  • 内置类型 int、list、str、set
  • 自定义的类

理解了以上这些概念,就很好理解 collections.defaultdict 的用法了

defaultdict

collections.defaultdict 是内置字典类型 dict 的一个派生类,和 dict 类的区别在于:

  • 重写了一个方法(__missing__())
  • 增加了一个位置参数(default_factory)

其余使用方法与 dict 完全相同。增加的 default_factory 参数用于生成默认值。

defaultdict(default_factory=None, /[, ...])

default_factory 的理念和可以取的值在 这一节 中介绍。

例子

基本的初始化方法

defaultdict 在最开始位置增加了 default_factory 参数用于生成默认值:

首先导入模块

>>> from collections import defaultdict

构造一个函数用于返回默认值

>>> def d():
...     return 'default'
...

实例化 defaultdict

>>> a=defaultdict(d)
>>> a
defaultdict(<function d at 0x000001BD3751DF70>, {})

访问一个不存在的key,这时自动生成 {1: 'default'} 的键值对

>>> a[1]
'default'

这一步的过程是:

  1. [1] 语法调用 __getitem__(1)
  2. __getitem__(1) 发现不存在 1 这个键
  3. __getitem__(1) 调用 __missing__()
  4. __missing__() 不带参数调用函数 d(),得到默认值'default'
  5. __missing__() 将不存在的键 1 和默认值'default'组成键值对,插入到自身对象中

查看对象的变化

>>> a
defaultdict(<function d at 0x000001BD3751DF70>, {1: 'default'})
>>>

这时已经有了 {1: 'default'} 的记录。

这样就是达到了用 [] 的语法实现 setdefault() 函数的目的。

其他形式的 default_factory

上一节 中介绍了自定义函数作为 default_factory 的例子,在 这一节 中提到,还有另外两种 default_factory 的形式:

  • 内置类型 int、list、str、set
  • 自定义的类

内置类型作为可调用对象(callable),返回的是空的默认值:

>>> int()
0
>>> str()
''
>>> list()
[]
>>> set()
set()
>>>

在一些统计的场合,可以直接用作 default_factory

这里举个来自标准库文档里归类的例子

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)
for k, v in s:
    d[k].append(v)

sorted(d.items())
# [('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

在第4行中,如果 d 中没有 k,则新建一个 {k: []} 的记录,并且返回空列表 [] 的引用,仿佛存在 k 一般。

所以,无论 d 中有没有 k,都使得循环体能够持续执行。整个代码非常简洁、易读。

如果用 setdefault(),第4行将成为:

d.setdefault(k, []).append(v)

工厂函数

如果像 这一节 中自定义函数用作 default_factory ,只能返回一个固定值。如果希望将这个固定值参数化,可以使用工厂函数的方法。

普通函数:

def d():
    return 'default'

工厂函数:

def d(count):
    def f():
      return count

    return f

工厂函数返回的是一个函数,这样无参数调用 d(count) ,实质上调用的是 f()

>>> a=defaultdict(d(10))
>>> a[1]
10
>>> a
defaultdict(<function d.<locals>.f at 0x1076e4550>, {1: 10})
>>>

工厂函数还能简单地写成匿名 lambda 函数:

def d(count):
    return lambda: count

效果和上面的一致。

其他初始化方法

先看 dict 类型的用法,有三种初始化的方法:

# dict()
>>> dict()
{}
>>> 

# dict(**kwarg)
>>> dict(one=1, two=2, three=3)
{'one': 1, 'two': 2, 'three': 3}
>>>

# dict(mapping, **kwarg)
>>> dict({'one': 1, 'two': 2, 'three': 3})
{'one': 1, 'two': 2, 'three': 3}
>>>

# dict(iterable, **kwarg)
>>> dict([('two', 2), ('one', 1), ('three', 3)])
{'two': 2, 'one': 1, 'three': 3}
>>>

既然 defaultdict 继承了 dict 的行为,那么上述 dict 的初始化方法也都适用。

>>> def d(count):
...     return lambda: count
...
>>> a=defaultdict(d(4), one=1, two=2, three=3)
>>> a['four']
4
>>> list(a.items())
[('one', 1), ('two', 2), ('three', 3), ('four', 4)]
>>>

各位读后有什么想法,请在下方留言吧!如果对本文有疑问或者寻求合作,欢迎 联系邮箱邮箱已到剪贴板

精彩评论