我提供了一个工作实例,在这个实例中,我有一个在Python 3中作为自定义类型实现的动态数组。我希望使用这个动态数组的单个实例作为一个通用资源来实现,比如说。N
堆栈。我怎么做呢?
我想,我想让每个堆栈只访问特定部分的 DynamicArray
划清界线 _start
和 _end
. 为了有 _start
和 _end
对于每一个堆栈,我想把它们包在一个帮助类中。_StackRecord
. 如果我成功地提供了一个可修改的观点,那么,我就可以在此基础上进行修改。DynamicArray
我想 _StackRecord
来完成所有的弹出和推送的重任,使堆栈不发生碰撞,而底层的人却能得到更好的服务。DynamicArray
根据需要扩大缩小。我知道我的要求太高了,但我可能会在做不到这一点的时候学到一些无用的技能。
任何对模块化、可维护性和良好实践的建议批评都是全心全意的欢迎。
import ctypes
class DynamicArray:
"""Expandable array class similar to Python list"""
def __init__(self, size=0):
self._n = size
self._capacity = size + 1
self._A = self._make_low_level_array(self._capacity)
def _make_low_level_array(self, capacity):
return (capacity*ctypes.py_object)()
# following two methods are needed for Python to implement __iter__
def __len__(self):
return self._n
def __getitem__(self, index_key):
if isinstance(index_key, slice):
start, stop, step = index_key.indices(len(self))
return [self._A[i] for i in range(start, stop, step)]
elif isinstance(index_key, int):
if 0 <= index_key < self._n :
return self._A[index_key]
else:
raise IndexError("index out of bounds")
elif isinstance(index_key, tuple):
raise NotImplementedError('Tuple as index')
else:
raise TypeError('Invalid argument type: {}'.format(type(key)))
def __setitem__(self, index_k, value):
if 0 <= index_k < self._n :
self._A[index_k] = value
else:
raise IndexError("index out of bounds")
###################################################################
class FixedMultiStack:
class _StackRecord(DynamicArray):
def __init__(self, array: DynamicArray, stack_number=0, size_of_each=10):
self._stack = stack_number
self._start = stack_number*size_of_each
self._end = self._start + size_of_each
# try commenting the following lines
self._n = size_of_each
self._A = DynamicArray(self._n)
# If I have to use self._A then I would like it to point
# to array[self._start:self._end]
for i in range(self._start, self._end):
array[i] = i
for i in range(self._n):
self._A[i] = array[self._start+ i]
def __init__(self, numStack=1, sizeEach=10):
self._stacks = []
self._items = DynamicArray(numStack*sizeEach)
for i in range(numStack):
self._stacks.append(self._StackRecord(self._items, i, sizeEach))
def __getitem__(self, stack_number):
return self._stacks[stack_number]
if __name__ == "__main__":
fms = FixedMultiStack(3,10)
print(list(fms[0]))
print(list(fms[1]))
print(list(fms[2]))
print(list(fms._items))
我在做浪费的行为,做了一个叫做地方副本的行为。self._A
. 我如何避免这种情况?为什么我不能在传递给本地记录保存者的全局动态数组上工作呢?_StackRecord
?
fms = FixedMultiStack(3,10)
, 一个固定的多堆栈包装3个堆栈,每个堆栈大小为10,这样
我想,如果 self._A
必要时,当地 self._A
指该部分 DynamicArray
对应于给定的栈号。
所以 print(list(fms[n]))
给我第n个栈的内容
而 print(list(fms._items))
应该给我所有堆栈的联合状态。Yikes! print(list(fms._items))
是丑陋的。怎么样 print(list(fms))
?
我应该可以写出这样的内容 self._items[n].push(val)
, self._items[n].pop()
来推送和弹出第n个栈。
你可以使用 memoryview
用于在整个数组上创建不同的视图。
class FixedMultiStack:
def __init__(self, m, n):
self.data = bytearray(m*n)
view = memoryview(self.data)
self.stacks = [view[i*n:(i+1)*n] for i in range(m)]
def __getitem__(self, index):
return self.stacks[index]