python:带有非默认参数的defaultdict

use*_*620 4 python dictionary defaultdict karma-runner

我想要类似a dict的东西,class TestClass其中包含非默认参数。当我访问时,我不知道要问的元素是否早于此。因此TestClass

class TestClass(object):
    def __init__(self, name):
        self.name = name
        self.state = 0
    def getName(self):
        self.state = self.state + 1
        return "%s -- %i" % (self.name, self.state)
Run Code Online (Sandbox Code Playgroud)

然后dict和访问函数:

db = {}
def getOutput(key):
    # this is a marvel in the world of programming langauges
    if key not in db:
        db[key] = TestClass(key)
    return db[key]
Run Code Online (Sandbox Code Playgroud)

以及实际的测试代码:

if __name__ == "__main__":
    print "testing: %s" % getOutput('charlie').getName()
Run Code Online (Sandbox Code Playgroud)

真好 但是我想知道是否有更优雅的解决方案。浏览时,defaultdict进入了我的脑海。但这是行不通的,因为我无法将参数传递给default_factory

from collections import defaultdict
d = defaultdict(TestClass)
print "testing %s" % d['tom'].getOutput()
Run Code Online (Sandbox Code Playgroud)

TypeError: __init__() takes exactly 2 arguments (1 given)...我还有另一种解决方案?

此外,我想改进我的Python。因此,任何其他建议也欢迎;-)

Mar*_*ers 7

defaultdict工厂的确不带参数。

你可以创建自己的变体确实然而,诀窍在于定义__missing__方法:

class TestClassDict(dict):
    def __missing__(self, key):
        res = self[key] = TestClass(key)
        return res
Run Code Online (Sandbox Code Playgroud)

每当dict[key]访问不存在的时key__missing__都会调用该方法。每次都defaultdict使用此钩子返回factory(),但是您可以提供自己的并传递key

演示:

>>> class TestClass(object):
...     def __init__(self, name):
...         self.name = name
...         self.state = 0
...     def getName(self):
...         self.state = self.state + 1
...         return "%s -- %i" % (self.name, self.state)
... 
>>> class TestClassDict(dict):
...     def __missing__(self, key):
...         res = self[key] = TestClass(key)
...         return res
... 
>>> db = TestClassDict()
>>> db['charlie'].getName()
'charlie -- 1'
>>> db
{'charlie': <__main__.TestClass object at 0x102f72250>}
Run Code Online (Sandbox Code Playgroud)