Mor*_*ock 169 python dictionary nested
感谢SO的一些优秀人员,我发现了collections.defaultdict
可见性和速度提供的可能性.我已经把它们用于成功.
现在我想实现三个级别的词典,两个顶级词典defaultdict
和最低词典int
.我找不到合适的方法来做到这一点.这是我的尝试:
from collections import defaultdict
d = defaultdict(defaultdict)
a = [("key1", {"a1":22, "a2":33}),
("key2", {"a1":32, "a2":55}),
("key3", {"a1":43, "a2":44})]
for i in a:
d[i[0]] = i[1]
Run Code Online (Sandbox Code Playgroud)
现在这可行,但以下,这是所需的行为,不会:
d["key4"]["a1"] + 1
Run Code Online (Sandbox Code Playgroud)
我怀疑我应该声明第二级defaultdict
是类型的int
,但我没有找到在哪里或如何这样做.
我defaultdict
首先使用的原因是避免为每个新密钥初始化字典.
还有更优雅的建议吗?
谢谢pythoneers!
int*_*jay 326
使用:
from collections import defaultdict
d = defaultdict(lambda: defaultdict(int))
Run Code Online (Sandbox Code Playgroud)
defaultdict(int)
每当访问新密钥时,这将创建一个新的d
.
Nat*_*ile 31
制作pickleable嵌套defaultdict的另一种方法是使用部分对象而不是lambda:
from functools import partial
...
d = defaultdict(partial(defaultdict, int))
Run Code Online (Sandbox Code Playgroud)
这将起作用,因为defaultdict类可在模块级别全局访问:
"你不能挑选一个部分对象,除非它包装的函数[或者在这种情况下,类]是全局可访问的......在它的__name__(在__module__中)" - Pickling 包含的部分函数
mil*_*s82 12
请看一下nosklo的答案,以获得更通用的解决方案.
Run Code Online (Sandbox Code Playgroud)class AutoVivification(dict): """Implementation of perl's autovivification feature.""" def __getitem__(self, item): try: return dict.__getitem__(self, item) except KeyError: value = self[item] = type(self)() return value
测试:
Run Code Online (Sandbox Code Playgroud)a = AutoVivification() a[1][2][3] = 4 a[1][3][3] = 5 a[1][2]['test'] = 6 print a
输出:
Run Code Online (Sandbox Code Playgroud){1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
聚会迟到了,但为了任意深度,我发现自己在做这样的事情:
from collections import defaultdict
class DeepDict(defaultdict):
def __call__(self):
return DeepDict(self.default_factory)
Run Code Online (Sandbox Code Playgroud)
这里的技巧基本上是使DeepDict
实例本身成为构建缺失值的有效工厂。现在我们可以做这样的事情
dd = DeepDict(DeepDict(list))
dd[1][2].extend([3,4])
sum(dd[1][2]) # 7
ddd = DeepDict(DeepDict(DeepDict(list)))
ddd[1][2][3].extend([4,5])
sum(ddd[1][2][3]) # 9
Run Code Online (Sandbox Code Playgroud)
按照@rschwieb的要求D['key'] += 1
,我们可以通过定义方法覆盖加法来扩展前一个__add__
方法,以使其表现得更像collections.Counter()
首先__missing__
将被调用以创建一个新的空值,该值将传递到中__add__
。我们测试该值,以空值为False
。
有关覆盖的更多信息,请参见模拟数字类型。
from numbers import Number
class autovivify(dict):
def __missing__(self, key):
value = self[key] = type(self)()
return value
def __add__(self, x):
""" override addition for numeric types when self is empty """
if not self and isinstance(x, Number):
return x
raise ValueError
def __sub__(self, x):
if not self and isinstance(x, Number):
return -1 * x
raise ValueError
Run Code Online (Sandbox Code Playgroud)
例子:
>>> import autovivify
>>> a = autovivify.autovivify()
>>> a
{}
>>> a[2]
{}
>>> a
{2: {}}
>>> a[4] += 1
>>> a[5][3][2] -= 1
>>> a
{2: {}, 4: 1, 5: {3: {2: -1}}}
Run Code Online (Sandbox Code Playgroud)
我们可以只提供默认的0值,然后尝试执行该操作,而不是检查参数是否为Number(非常非python,无粉动物!)。
class av2(dict):
def __missing__(self, key):
value = self[key] = type(self)()
return value
def __add__(self, x):
""" override addition when self is empty """
if not self:
return 0 + x
raise ValueError
def __sub__(self, x):
""" override subtraction when self is empty """
if not self:
return 0 - x
raise ValueError
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
60738 次 |
最近记录: |