这是我的版本,我称之为ArrayHash
。它的行为类似于数组,除非您使用字符串作为键,然后它开始像哈希表一样运作。它支持初始化、使用+
和+=
进行连接,以及在左侧和右侧进行切片。在数组模式下,如果您引用或分配给arrayhash[N],它将使用None
值从0..N-1填充。在哈希模式下,它停止执行此操作。它回答isinstance(arrayhash, dict)为True,并且即使在哈希模式下,isinstance(arrayhash, collections.abc.Sequence)也会返回True。我很想听听您的反馈!
from collections import defaultdict
import collections.abc
class _ArrayHash(defaultdict, collections.abc.Sequence):
def append(self, value):
self[len(self)] = value
def extend(self, lst):
ln = len(self)
for item in lst:
self[ln] = item
ln += 1
def update(self, values):
self.isHash = True
for k, v in values.items():
self[k] = v
def __getitem__(self, index):
if isinstance(index, slice):
return [self[i] for i in range(*index.indices(len(self)))]
elif isinstance(index, int):
if index < 0:
index += len(self)
return super().__getitem__(index)
else:
self.isHash = True
return super().__getitem__(index)
def __setitem__(self, index, value):
if isinstance(index, slice):
try:
if not hasattr(self, 'isHash'):
for i in range(len(self), index.start):
super().__setitem__(i, None)
value = iter(value)
ndx = index.start
for i in range(*index.indices(len(self))):
super().__setitem__(i, next(value))
ndx += 1
rest = list(value)
lr = len(rest)
if lr:
for i in range(len(self)-1,ndx-1,-1):
super().__setitem__(i+lr, super().__getitem__(i))
for i in range(lr):
super().__setitem__(i+ndx, rest[i])
except StopIteration:
pass
elif isinstance(index, int):
if index < 0:
index += len(self)
if not hasattr(self, 'isHash'):
for i in range(len(self), index):
super().__setitem__(i, None)
super().__setitem__(index, value)
else:
self.isHash = True
super().__setitem__(index, value)
def __iter__(self):
if hasattr(self, 'isHash'):
for i in self.keys():
yield i
else:
for i in range(len(self)):
yield self[i]
def __add__(self, other):
result = ArrayHash(self)
if hasattr(self, 'isHash') or (isinstance(other, dict) and not isinstance(other, _ArrayHash)) or hasattr(other, 'isHash'):
result.update(other)
else:
result.extend(other)
return result
def __iadd__(self, other):
if hasattr(self, 'isHash') or (isinstance(other, dict) and not isinstance(other, _ArrayHash)) or hasattr(other, 'isHash'):
self.update(other)
else:
self.extend(other)
return self
def __radd__(self, other):
result = ArrayHash()
if hasattr(self, 'isHash') or (isinstance(other, dict) and not isinstance(other, _ArrayHash)) or hasattr(other, 'isHash'):
result.update(other)
result.update(self)
else:
result.extend(other)
result.extend(self)
return result
def ArrayHash(init=None):
"""Acts like an array with autovivification, unless you use a string as a key, then it becomes a hash"""
result = _ArrayHash(ArrayHash)
if init is not None:
if isinstance(init, collections.abc.Sequence) and not isinstance(init, str):
result.extend(init)
elif isinstance(init, _ArrayHash):
if(hasattr(init, 'isHash')):
result.update(init)
else:
result.extend(init)
elif isinstance(init, dict):
result.update(init)
else:
result.append(init)
return result
a['x'].append('z')
或a['x']['y']['w'].append('z')
?谢谢。 - Zhang18