首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
V2EX  ›  Python

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

  •  
  •   ltoddy · 2018-10-06 12:07:57 +08:00 · 2259 次点击
    这是一个创建于 403 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 就太脏了.

    14 回复  |  直到 2018-10-08 15:06:54 +08:00
        1
    sww4718168   2018-10-06 13:11:27 +08:00
    这是为了模拟枚举么?为什么不直接用 enum
        2
    ltoddy   2018-10-06 14:39:45 +08:00
    @sww4718168 看来你是没看懂呀, 看看我说的最后一行那句话.
        3
    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'])
        4
    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()的局部变量
        5
    sww4718168   2018-10-06 15:33:06 +08:00
    @ltoddy 只是好奇应用场景是什么。
        6
    ltoddy   2018-10-06 16:58:00 +08:00
    @zh826256645 emmmm, 我可能当时在用闭包的时候眼瞎了.
        7
    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() 函数中做点事情, 然后就可以计算缓存命中率了, 然后你得到命中率之后, 你搞点事情,来避免缓存击穿问题之类的. (我刚吃完饭回到宿舍,刚刚编的.)
        8
    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'])
        9
    ltoddy   2018-10-07 06:04:18 +08:00 via Android
    @aijam 看来你也没看懂我想表达的想发。
        10
    macsed   2018-10-07 09:22:40 +08:00 via iPhone
    动态语言里面搞一个 XXXFactory,看来是连门都没入...
        11
    ltoddy   2018-10-07 10:09:42 +08:00 via Android
    @macsed 去看看 defaultdict 是如何定义的,看看它的形参名字怎么叫的。
        12
    ltoddy   2018-10-07 10:12:37 +08:00 via Android
    @macsed **Factory,估计你没听过 Python 元编程。
        13
    ltoddy   2018-10-07 10:13:03 +08:00 via Android
    @macsed 你看看那个类的名字,第一个字母是下划线,是你不懂啊,还是我不懂啊?
        14
    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}
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2781 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 29ms · UTC 12:12 · PVG 20:12 · LAX 04:12 · JFK 07:12
    ♥ Do have faith in what you're doing.