gpt4 book ai didi

python - 用 numpy 支持覆盖字典

转载 作者:太空宇宙 更新时间:2023-11-03 14:12:06 29 4
gpt4 key购买 nike

使用来自 How to "perfectly" override a dict? 的基本想法,我编写了一个基于字典的类,它应该支持分配点分隔键,即 Extendeddict('level1.level2', 'value') == {'level1':{'level2':'value'}}

代码是

import collections
import numpy

class Extendeddict(collections.MutableMapping):
"""Dictionary overload class that adds functions to support chained keys, e.g. A.B.C
:rtype : Extendeddict
"""
# noinspection PyMissingConstructor
def __init__(self, *args, **kwargs):
self._store = dict()
self.update(dict(*args, **kwargs))

def __getitem__(self, key):
keys = self._keytransform(key)
print 'Original key: {0}\nTransformed keys: {1}'.format(key, keys)
if len(keys) == 1:
return self._store[key]
else:
key1 = '.'.join(keys[1:])
if keys[0] in self._store:
subdict = Extendeddict(self[keys[0]] or {})
try:
return subdict[key1]
except:
raise KeyError(key)
else:
raise KeyError(key)

def __setitem__(self, key, value):
keys = self._keytransform(key)
if len(keys) == 1:
self._store[key] = value
else:
key1 = '.'.join(keys[1:])
subdict = Extendeddict(self.get(keys[0]) or {})
subdict.update({key1: value})
self._store[keys[0]] = subdict._store

def __delitem__(self, key):
keys = self._keytransform(key)
if len(keys) == 1:
del self._store[key]
else:
key1 = '.'.join(keys[1:])
del self._store[keys[0]][key1]
if not self._store[keys[0]]:
del self._store[keys[0]]

def __iter__(self):
return iter(self._store)

def __len__(self):
return len(self._store)

def __repr__(self):
return self._store.__repr__()

# noinspection PyMethodMayBeStatic
def _keytransform(self, key):
try:
return key.split('.')
except:
return [key]

但是使用 Python 2.7.10 和 numpy 1.11.0,运行

basic = {'Test.field': 'test'}
print 'Normal dictionary: {0}'.format(basic)
print 'Normal dictionary in a list: {0}'.format([basic])
print 'Normal dictionary in numpy array: {0}'.format(numpy.array([basic], dtype=object))
print 'Normal dictionary in numpy array.tolist(): {0}'.format(numpy.array([basic], dtype=object).tolist())

extended_dict = Extendeddict(basic)
print 'Extended dictionary: {0}'.format(extended_dict)
print 'Extended dictionary in a list: {0}'.format([extended_dict])
print 'Extended dictionary in numpy array: {0}'.format(numpy.array([extended_dict], dtype=object))
print 'Extended dictionary in numpy array.tolist(): {0}'.format(numpy.array([extended_dict], dtype=object).tolist())

我得到:

Normal dictionary: {'Test.field': 'test'}
Normal dictionary in a list: [{'Test.field': 'test'}]
Normal dictionary in numpy array: [{'Test.field': 'test'}]
Normal dictionary in numpy array.tolist(): [{'Test.field': 'test'}]
Original key: Test
Transformed keys: ['Test']
Extended dictionary: {'Test': {'field': 'test'}}
Extended dictionary in a list: [{'Test': {'field': 'test'}}]
Original key: 0
Transformed keys: [0]
Traceback (most recent call last):
File "/tmp/scratch_2.py", line 77, in <module>
print 'Extended dictionary in numpy array: {0}'.format(numpy.array([extended_dict], dtype=object))
File "/tmp/scratch_2.py", line 20, in __getitem__
return self._store[key]
KeyError: 0

而我希望 print 'Extended dictionary in numpy array: {0}'.format(numpy.array([extended_dict], dtype=object)) 产生 Extended dictionary在 numpy 数组中:[{'Test': {'field': 'test'}}]

关于这可能有什么问题有什么建议吗?这甚至是正确的方法吗?

最佳答案

问题出在 np.array 构造步骤中。它深入研究其输入,试图创建一个更高维的数组。

In [99]: basic={'test.field':'test'}

In [100]: eb=Extendeddict(basic)

In [104]: eba=np.array([eb],object)
<keys: 0,[0]>
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
<ipython-input-104-5591a58c168a> in <module>()
----> 1 eba=np.array([eb],object)

<ipython-input-88-a7d937b1c8fd> in __getitem__(self, key)
11 keys = self._keytransform(key);print key;print keys
12 if len(keys) == 1:
---> 13 return self._store[key]
14 else:
15 key1 = '.'.join(keys[1:])

KeyError: 0

但如果我创建一个数组,并分配对象,它就可以正常工作

In [105]: eba=np.zeros((1,),object)

In [106]: eba[0]=eb

In [107]: eba
Out[107]: array([{'test': {'field': 'test'}}], dtype=object)

np.array 是一个与 dtype=object 一起使用的棘手函数。比较 np.array([[1,2],[2,3]],dtype=object)np.array([[1,2],[2]], dtype=对象)。一个是 (2,2),另一个是 (2,)。它尝试制作一个二维数组,只有在失败时才使用列表元素求助于一维数组。沿着这条线的事情正在这里发生。

我看到了 2 个解决方案 - 一个是关于构建数组的方法,我在其他场合也使用过。另一个是弄清楚为什么 np.array 不深入研究 dict 而对你的进行研究。 np.array 已编译,因此可能需要阅读艰难的 GITHUB 代码。


我尝试了一个使用 f=np.frompyfunc(lambda x:x,1,1) 的解决方案,但这不起作用(有关详细信息,请参阅我的编辑历史记录)。但我发现将 Extendeddictdict 混合使用确实有效:

In [139]: np.array([eb,basic])
Out[139]: array([{'test': {'field': 'test'}}, {'test.field': 'test'}], dtype=object)

将它与 None 或空列表等其他内容混合也是如此

In [140]: np.array([eb,[]])
Out[140]: array([{'test': {'field': 'test'}}, []], dtype=object)

In [142]: np.array([eb,None])[:-1]
Out[142]: array([{'test': {'field': 'test'}}], dtype=object)

这是构造列表对象数组的另一个常用技巧。

如果你给它两个或多个不同长度的Extendeddict,它也可以工作

np.array([eb, Extendeddict({})])。换句话说,如果 len(...) 不同(就像混合列表一样)。

关于python - 用 numpy 支持覆盖字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36663919/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com