# v1 # Written by nortti # Under Unlicense from functools import reduce import operator class RankError(Exception): None class RectangularArray: def __init__(self, sizes, *, default = None, initial = None): if isinstance(sizes, int): self.sizes = (sizes,) else: self.sizes = tuple(sizes) self.rank = len(self.sizes) combined_size = reduce(operator.mul, self.sizes) if initial is None: self.array = [default] * combined_size else: if len(initial) != combined_size: raise ValueError('Initial array of wrong size passed (expected %i, got %i)' % (combined_size, len(initial))) def __get_location_from_indices(self, indices): if isinstance(indices, int): indices = (indices,) else: indices = tuple(indices) if len(indices) != self.rank: raise RankError('Rank mismatch accessing array (expected %i, got %i)' % (self.rank, len(indices))) location = 0 for dimension in range(self.rank): index = indices[dimension] size = self.sizes[dimension] if index >= size: raise IndexError('Index Out of Range (is %i, max %i)' % (index, self.sizes[dimension] - 1)) location *= size location += index return location def __getitem__(self, indices): location = self.__get_location_from_indices(indices) return self.array[location] def __setitem__(self, indices, value): location = self.__get_location_from_indices(indices) self.array[location] = value def __repr__(self): return 'RectangularArray(%s, initial = %s)' % (repr(self.sizes), repr(self.array))