分享一段关于Python中defaultdict用法的代码

from collections import defaultdict

class _DefaultFactory: def init(self): self.count = 0

def __call__(self):
    self.count = self.count + 1
    return self.count

default_factory = _DefaultFactory() d = defaultdict(default_factory)

print(d[‘foo’]) print(d[‘bar’])

使用闭包是做不到的.

使用 top-level variable 就太脏了.


分享一段关于Python中defaultdict用法的代码

15 回复

这是为了模拟枚举么?为什么不直接用 enum


from collections import defaultdict

# 场景1: 统计单词出现次数
words = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']
word_count = defaultdict(int)  # 默认值为0

for word in words:
    word_count[word] += 1

print(word_count)  # defaultdict(<class 'int'>, {'apple': 3, 'banana': 2, 'orange': 1})

# 场景2: 按首字母分组单词
words = ['apple', 'ant', 'banana', 'bear', 'cat', 'car']
grouped = defaultdict(list)  # 默认值为空列表

for word in words:
    grouped[word[0]].append(word)

print(grouped)  
# defaultdict(<class 'list'>, {'a': ['apple', 'ant'], 'b': ['banana', 'bear'], 'c': ['cat', 'car']})

# 场景3: 嵌套字典
nested = defaultdict(lambda: defaultdict(int))  # 两层嵌套
nested['fruit']['apple'] = 5
nested['fruit']['banana'] = 3
nested['animal']['cat'] = 2

print(nested['fruit'])  # defaultdict(<class 'int'>, {'apple': 5, 'banana': 3})
print(nested['vehicle'])  # 自动创建: defaultdict(<class 'int'>, {})

# 场景4: 自定义默认值函数
def default_price():
    return 9.99

prices = defaultdict(default_price)
prices['apple'] = 5.99
print(prices['apple'])   # 5.99 (已设置的值)
print(prices['banana'])  # 9.99 (使用默认函数)

defaultdict的核心优势就是访问不存在的键时不会报KeyError,而是返回你指定的默认值。用普通dict的话,上面这些场景都得先判断key是否存在,代码会啰嗦很多。

一句话总结:用defaultdict能让分组和计数代码更简洁。

看来你是没看懂呀, 看看我说的最后一行那句话.

from collections import defaultdict


def _DefaultFactory():
count = [0]
def wrap():
count[0] = count[0] + 1
return count[0]
return wrap


default_factory = _DefaultFactory()
d = defaultdict(default_factory)

print(d[‘foo’])
print(d[‘bar’])

from collections import defaultdict


def _DefaultFactory():
count = 0

def wrap():
nonlocal count
count += 1
return count
return wrap


default_factory = _DefaultFactory()
d = defaultdict(default_factory)

print(d[‘foo’])
print(d[‘bar’])

或者指明 count 不是 wrap()的局部变量

只是好奇应用场景是什么。

emmmm, 我可能当时在用闭包的时候眼瞎了.

来,我编一个例子, 假设你有一个 key-value 的缓存基于 defaultdict 做的, 然后呢,

> defaultdict(default_factory)

default_factory 是一个可以被 invoke 的对象, 你直接把他当作函数就好了.

然后呢, 当 miss key 之后,那个 default_factory 就会被调用一次, 这个样子的, 你可以在 getitem 和 get() 函数中做点事情, 然后就可以计算缓存命中率了, 然后你得到命中率之后, 你搞点事情,来避免缓存击穿问题之类的. (我刚吃完饭回到宿舍,刚刚编的.)

from collections import defaultdict
from itertools import count

d = defaultdict(count(1).next)

print(d[‘foo’])
print(d[‘bar’])

看来你也没看懂我想表达的想发。

动态语言里面搞一个 XXXFactory,看来是连门都没入…

去看看 defaultdict 是如何定义的,看看它的形参名字怎么叫的。

**Factory,估计你没听过 Python 元编程。

你看看那个类的名字,第一个字母是下划线,是你不懂啊,还是我不懂啊?

就实现这么个功能至于绕那么大弯么?就会这点玩意儿至于那么膨胀么?

from collections import UserDict


class CntDict(UserDict):

→ def init(self):
→ → self.data = {}
→ → self.count = 0

→ def getitem(self, key):
→ → if key not in self.data:
→ → → self.count = self.count + 1
→ → → self.data[key]= self.count
→ → → return self.data[key]

d = CntDict()

print(d[‘foo’])
print(d[‘bar’])
print(d[‘xxx’])
print(d)

# 1
# 2
# 3
# {‘foo’: 1, ‘bar’: 2, ‘xxx’: 3}

回到顶部