On Thu, 24 May 2018 16:05:32 -0700, Paul wrote: > How would one make a multi-dimensional list now, with truly-separate sub > lists? Is there just no way to do it with the replication operator?
Correct. Let's say you want to make a 1-D list with three items initialised to zero. This works brilliantly: py> [0]*3 [0, 0, 0] This seems like it ought to create a 3x3 2-D list: py> y = [[0]*3]*3 py> y [[0, 0, 0], [0, 0, 0], [0, 0, 0]] but alas, it's a trap: py> y[0][0] = 1 py> y [[1, 0, 0], [1, 0, 0], [1, 0, 0]] The current recommended solution is: py> y = [[0]*3 for _ in range(3)] py> y[0][0] = 1 py> y [[1, 0, 0], [0, 0, 0], [0, 0, 0]] To get a three-dimensional 3x3x3 list is even more work: py> z = [[[0]*3 for _ in range(3)] for _ in range(3)] py> z[0][0][0] = 1 py> z[1][1][1] = 2 py> z[2][2][2] = 3 py> z [[[1, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 2, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 3]]] With my suggestion, we get: x = [0]**3 # one-dimensional y = [[0]**3]**3 # two-dimensional z = [[[0]**3]**3]**3 # three-dimensional Or there's MRAB's suggestion of using @ instead. The one-dimensional case can be optimized by using regular * replication instead of ** duplication, but that's an optimization for immutable objects. Here's a subclass that implements a simple version of this for testing: class ML(list): def __pow__(self, other): import copy L = [] for i in range(other): L.extend(copy.deepcopy(obj) for obj in self) return ML(L) And in use to generate a 3-D list: py> z = ML([ML([ML([0])**3])**3])**3 py> z[0][0][0] = 1 py> z[1][1][1] = 2 py> z[2][2][2] = 3 py> z [[[1, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 2, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 3]]] The repeated calls to ML() are ugly and are only there because the [] syntax creates ordinary lists, not my subclass. -- Steve -- https://mail.python.org/mailman/listinfo/python-list