使用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]
但是在Python2.7.10和Numpy1.11.0中
^{pr2}$我得到:
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))
产生{
你有什么建议吗?这样做对吗?在
问题出在
np.array
构造函数步骤中。它挖掘输入,试图创建一个高维数组。在但如果我做一个数组,并分配对象,它可以很好地工作
^{pr2}$np.array
是一个与dtype=object
一起使用的复杂函数。比较np.array([[1,2],[2,3]],dtype=object)
和{我看到了两个解决方案-一个是关于构造数组的方法,我在其他场合也用过。另一个是要弄清楚为什么
np.array
没有深入dict
而是你的。np.array
已编译,因此可能需要读取棘手的GITHUB代码。在我用
f=np.frompyfunc(lambda x:x,1,1)
尝试了一个解决方案,但是没有用(有关详细信息,请参阅我的编辑历史记录)。但我发现将Extendeddict
与dict
混合使用确实有效:将它与
None
或空列表混合使用也是如此这是构造列表对象数组的另一个常见技巧。在
如果给它两个或两个以上不同长度的
Extendeddict
,它也可以工作np.array([eb, Extendeddict({})])
。换句话说,如果len(...)
不同(就像混合列表一样)。在纽比试着做它应该做的事情:
Numpy会检查每个元素是否是iterable(通过使用
len
和iter
),因为传入的内容可能被解释为多维数组。在这里有一个问题:
dict
-类类(意思是isinstance(element, dict) == True
)不会被解释为另一个维度(这就是为什么传入[{}]
起作用的原因)。也许他们应该检查它是不是一个collections.Mapping
而不是dict
。也许你可以在他们的issue tracker上写一个bug。在如果将类定义更改为:
或更改
^{pr2}$__len__
-方法:它起作用了。这两种方法都不是你想做的,但是numpy只是使用duck-typing来创建数组,并且没有直接从},这是相当聪明和方便的。我认为这是一个错误。在
dict
派生子类,或者通过使len
不可访问,numpy将你的类看作应该是另一个维度的东西。如果您想传入自定义序列(来自collections.Sequence
的子类),但对于collections.Mapping
或{相关问题 更多 >
编程相关推荐