分享一段 Python 代码(关于 defaultdict 的)

2018-10-06 12:07:57 +08:00
 ltoddy
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 就太脏了.

3223 次点击
所在节点    Python
14 条回复
sww4718168
2018-10-06 13:11:27 +08:00
这是为了模拟枚举么?为什么不直接用 enum
ltoddy
2018-10-06 14:39:45 +08:00
@sww4718168 看来你是没看懂呀, 看看我说的最后一行那句话.
binux
2018-10-06 15:16:11 +08:00
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'])
zh826256645
2018-10-06 15:31:44 +08:00
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()的局部变量
sww4718168
2018-10-06 15:33:06 +08:00
@ltoddy 只是好奇应用场景是什么。
ltoddy
2018-10-06 16:58:00 +08:00
@zh826256645 emmmm, 我可能当时在用闭包的时候眼瞎了.
ltoddy
2018-10-06 17:01:03 +08:00
@sww4718168 来,我编一个例子, 假设你有一个 key-value 的缓存基于 defaultdict 做的, 然后呢,

> defaultdict(default_factory)

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

然后呢, 当 miss key 之后,那个 default_factory 就会被调用一次, 这个样子的, 你可以在 __getitem__ 和 get() 函数中做点事情, 然后就可以计算缓存命中率了, 然后你得到命中率之后, 你搞点事情,来避免缓存击穿问题之类的. (我刚吃完饭回到宿舍,刚刚编的.)
aijam
2018-10-07 03:18:20 +08:00
from collections import defaultdict
from itertools import count

d = defaultdict(count(1).__next__)

print(d['foo'])
print(d['bar'])
ltoddy
2018-10-07 06:04:18 +08:00
@aijam 看来你也没看懂我想表达的想发。
macsed
2018-10-07 09:22:40 +08:00
动态语言里面搞一个 XXXFactory,看来是连门都没入...
ltoddy
2018-10-07 10:09:42 +08:00
@macsed 去看看 defaultdict 是如何定义的,看看它的形参名字怎么叫的。
ltoddy
2018-10-07 10:12:37 +08:00
@macsed **Factory,估计你没听过 Python 元编程。
ltoddy
2018-10-07 10:13:03 +08:00
@macsed 你看看那个类的名字,第一个字母是下划线,是你不懂啊,还是我不懂啊?
xpresslink
2018-10-08 15:06:54 +08:00
就实现这么个功能至于绕那么大弯么?就会这点玩意儿至于那么膨胀么?

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}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/495153

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX