2014-09-20 68 views
3

我想有一个像dictclass TestClass它有一个非默认参数。当我访问时,我不知道所请求的元素是否已经存在。所以TestClasspython:defaultdict与非默认参数

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) 

然后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] 

和实际测试代码:

if __name__ == "__main__": 
    print "testing: %s" % getOutput('charlie').getName() 

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

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

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

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

回答

4

defaultdict工厂确实没有参数。

然而,您可以创建自己的变体,即确实是;关键是在定义__missing__方法:

class TestClassDict(dict): 
    def __missing__(self, key): 
     res = self[key] = TestClass(key) 
     return res 

每当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>} 
+0

很好的解决方案。谢谢! – user3474620 2014-09-20 20:09:06

+0

这真的很酷,我能找到的唯一答案很容易显示如何做到这一点 – citizen2077 2017-06-16 10:22:15