这是我的版本,我称之为ArrayHash
. 除非您使用字符串作为键,否则它的行为就像一个数组,然后它的行为就像一个散列。它支持LHS 和 RHS 上的初始化、与+
and的连接和切片。+=
在数组模式下,如果引用或分配给arrayhash[N],它会从0..N-1 开始填充None
值。在哈希模式下,它会停止这样做。它以 True 回答 isinstance(arrayhash, dict),即使它处于哈希模式,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): # Move everything else up
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