def test_insert(self): example_int = ArrayList(1, 2, 3, 4, 5) example_float = ArrayList(1., 2, 3, 4, 5) example_str = ArrayList("first", "second", "third") example_int.insert(2, 10) example_float.insert(2, 15.) example_str.insert(1, "$") self.assertEqual(example_int[2], 10) self.assertEqual(example_float[2], 15) self.assertEqual(example_str[1], "$")
class Collection(object): """ A collection is a container for several objects having the same vertex structure (vtype) and same uniforms type (utype). A collection allows to manipulate objects individually but they can be rendered at once (single call). Each object can have its own set of uniforms provided they are a combination of floats. """ def __init__(self, vtype, utype, itype=np.uint32 ): """ Parameters ---------- vtype: np.dtype Vertices data type utype: np.dtype Uniforms data type itype: np.dtype Indices data type """ vtype = np.dtype(vtype) if vtype.names is None: raise ValueError("vtype must be a structured dtype") utype = np.dtype(utype) if utype.names is None: raise ValueError("utype must be a structured dtype") itype = np.dtype(itype) if itype not in [np.uint8, np.uint16, np.uint32]: raise ValueError("itype must be unsigned integer or None") # Convert types to lists (in case they were already dtypes) such that # we can append new fields #vtype = eval(str(np.dtype(vtype))) # We add a uniform index to access uniform data #vtype.append( ('a_index', 'f4') ) #vtype = np.dtype(vtype) # Check utype is made of float32 only utype = eval(str(np.dtype(utype))) r_utype = dtype_reduce(utype) if type(r_utype[0]) is not str or r_utype[2] != 'float32': raise RuntimeError("Uniform type cannot be reduced to float32 only") # Make utype divisible by 4 count = int(math.pow(2, math.ceil(math.log(r_utype[1], 2)))) if (count - r_utype[1]) > 0: utype.append(('unused', 'f4', count-r_utype[1])) self._u_float_count = count # Create relevant array lists self._vertices = ArrayList(dtype=vtype) self._indices = ArrayList(dtype=itype) self._uniforms = ArrayList(dtype=utype) @property def u_shape(self): """ Uniform texture shape """ # max_texsize = gl.glGetInteger(gl.GL_MAX_TEXTURE_SIZE) max_texsize = 4096 cols = max_texsize//(self._u_float_count/4) rows = (len(self) // cols)+1 return rows, cols*(self._u_float_count/4), self._u_float_count @property def vertices(self): """ Vertices buffer """ return self._vertices @property def indices(self): """ Indices buffer """ return self._indices @property def uniforms(self): """ Uniforms buffer """ return self._uniforms @property def u_indices(self): """ Uniform texture indices """ return np.repeat(np.arange(len(self)), self._vertices.itemsize) def __len__(self): """ """ return len(self._vertices) def __getitem__(self, key): """ """ V, U, I = self._vertices, self._uniforms, self._indices if V.dtype.names and key in V.dtype.names: return V[key] elif U.dtype.names and key in U.dtype.names: return U[key] else: return Item(self, key, V[key], I[key], U[key]) def __setitem__(self, key, data): """ """ # Setting vertices field at once if self._vertices.dtype.names and key in self._vertices.dtype.names: self._vertices.data[key] = data # Setting uniforms field at once elif self._uniforms.dtype.names and key in self._uniforms.dtype.names: self._uniforms.data[key] = data # Setting individual item else: vertices, indices, uniforms = data del self[key] self.insert(key, vertices, indices, uniforms) def __delitem__(self, key): """ x.__delitem__(y) <==> del x[y] """ if type(key) is int: if key < 0: key += len(self) if key < 0 or key > len(self): raise IndexError("Collection deletion index out of range") kstart, kstop = key, key+1 # Deleting several items elif type(key) is slice: kstart, kstop, _ = key.indices(len(self)) if kstart > kstop: kstart, kstop = kstop,kstart if kstart == kstop: return elif key is Ellipsis: kstart, kstop = 0, len(self) # Error else: raise TypeError("Collection deletion indices must be integers") vsize = len(self._vertices[key]) del self._indices[key] self._indices[key] -= vsize del self._vertices[key] del self._uniforms[key] # Update a_index at once # I = np.repeat(np.arange(len(self)), self._vertices.itemsize) # self._vertices['a_index'] = I def insert(self, index, vertices, indices, uniforms=None, itemsize=None): """ Parameters ---------- index : int Index before which to insert data vertices : numpy array An array whose dtype is compatible with self.vertices.dtype indices : numpy array An array whose dtype is compatible with self.indices.dtype All index values must be between 0 and len(vertices) uniforms: numpy array An array whose dtype is compatible with self.uniforms.dtype itemsize: int or 1-D array If `itemsize is an integer, N, the array will be divided into elements of size N. If such partition is not possible, an error is raised. If `itemsize` is 1-D array, the array will be divided into elements whose succesive sizes will be picked from itemsize. If the sum of itemsize values is different from array size, an error is raised. """ # Make sure vertices/indices/uniforms are of the right dtype vtype = self._vertices.dtype vertices = np.array(vertices,copy=False).astype(vtype).ravel() itype = self._indices.dtype indices = np.array(indices,copy=False).astype(itype).ravel() utype = self._uniforms.dtype if uniforms is not None: uniforms = np.array(uniforms,copy=False).astype(utype).ravel() # Check index if index < 0: index += len(self) if index < 0 or index > len(self): raise IndexError("Collection insertion index out of range") # Inserting if index < len(self._vertices): vstart = self._vertices._items[index][0] istart = self._indices._items[index][0] ustart = self._uniforms._items[index][0] # Appending else: vstart = self._vertices.size istart = self._indices.size ustart = self._uniforms.size # Updating indices self._indices._data[istart:] += len(vertices) indices += vstart # Inserting one item if itemsize is None: #self._vertices[index:]['a_index'] += 1 #vertices['a_index'] = index self._vertices.insert(index,vertices) self._indices.insert(index,indices) if uniforms is not None: self._uniforms.insert(index,uniforms) else: U = np.zeros(1,dtype=self._uniforms.dtype) self._uniforms.insert(index,U) # Update a_index at once # I = np.repeat(np.arange(len(self)), self._vertices.itemsize) # self._vertices['a_index'] = I return # No item size specified if itemsize is None: v_itemcount = 1 v_itemsize = np.ones(1,dtype=int)*vertices.size i_itemcount = 1 i_itemsize = np.ones(1,dtype=int)*indices.size # Vertices size specified but no indices size if type(itemsize) is int: v_itemcount = vertices.size // itemsize v_itemsize = itemsize*np.ones(v_itemcount,dtype=int) i_itemcount = v_itemcount i_itemsize = len(indices)*np.ones(i_itemcount,dtype=int) indices = np.resize(indices, len(indices)*i_itemcount) # Vertices and indices size specified elif isinstance(itemsize, tuple): v_itemsize = itemsize[0] v_itemcount = vertices.size // v_itemsize v_itemsize = v_itemsize*np.ones(v_itemcount,dtype=int) i_itemsize = itemsize[1] i_itemcount = indices.size // i_itemsize i_itemsize = i_itemsize*np.ones(i_itemcount, dtype=int) # Vertices have different size else: itemsize = np.array(itemsize, copy=False) v_itemsize = itemsize[:,0] i_itemsize = itemsize[:,1] # Sanity check if (vertices.size % v_itemsize.sum()) != 0: raise ValueError("Cannot partition vertices data as requested") if (indices.size % i_itemsize.sum()) != 0: raise ValueError("Cannot partition indices data as requested") if v_itemcount != i_itemcount: raise ValueError("Vertices/Indices item size not compatible") I = np.repeat(v_itemsize.cumsum(),i_itemsize) indices[i_itemsize[0]:] += I[:-i_itemsize[0]] self._vertices.insert(index, vertices, v_itemsize) self._indices.insert(index, indices, i_itemsize) if uniforms is None: U = np.zeros(v_itemcount,dtype=self._uniforms.dtype) self._uniforms.insert(index,U, itemsize=1) else: if len(uniforms) != v_itemcount: if len(uniforms) == 1: U = np.resize(uniforms, v_itemcount) self._uniforms.insert(index, U, itemsize=1) else: raise ValueError("Vertices/Uniforms item number not compatible") else: self._uniforms.insert(index, uniforms, itemsize=1) # Update a_index at once I = np.repeat(np.arange(len(self)), self._vertices.itemsize) self._vertices['a_index'] = I def append(self, vertices, indices, uniforms=None, itemsize=None): """ Parameters ---------- vertices : numpy array An array whose dtype is compatible with self.vertices.dtype indices : numpy array An array whose dtype is compatible with self.indices.dtype All index values must be between 0 and len(vertices) uniforms: numpy array An array whose dtype is compatible with self.uniforms.dtype itemsize: int, tuple or 1-D array If `itemsize is an integer, N, the array will be divided into elements of size N. If such partition is not possible, an error is raised. If `itemsize` is 1-D array, the array will be divided into elements whose succesive sizes will be picked from itemsize. If the sum of itemsize values is different from array size, an error is raised. """ self.insert(len(self), vertices, indices, uniforms, itemsize)
def test_insert_4(self): L = ArrayList() L.append(1) L.insert(-1, np.arange(10), 1 + np.arange(4)) assert len(L) == 5 assert np.allclose(L[3], [6, 7, 8, 9])
def test_insert_2(self): L = ArrayList() L.append(1) L.insert(0, np.arange(10), 2) assert len(L) == 6 assert np.allclose(L[4], [8, 9])
def test_insert_1(self): L = ArrayList() L.append(1) L.insert(0, 2) assert len(L) == 2 assert L[0] == 2
class TestArrayList(TestCase): def setUp(self): self.al = ArrayList() def test_append__when_list_is_empty__should_add_to_then_end(self): self.al.append(1) values = list(self.al) self.assertEqual([1], values) def test_append__to_return(self): result = self.al.append(1) self.assertEqual(self.al, result) def test_append__when_list_is_not_empty__should_add_to_then_end(self): self.al.append(1) self.al.append(2) self.al.append(3) values = list(self.al) self.assertEqual([1, 2, 3], values) def test_append__1024_values_expect_append__to_the_end(self): values = [x for x in range(1024)] [self.al.append(x) for x in values] list_values = list(self.al) self.assertEqual(values, list_values) def test_remove__when_index_is_valid__expect_remove_values_and_return_it( self): self.al.append(1) self.al.append(2) self.al.append(33) self.al.append(4) result = self.al.remove(2) self.assertEqual([1, 2, 4], list(self.al)) self.assertEqual(33, result) def test_remove__when_index_is_invalid__expect_remove_values_and_raise( self): self.al.append(1) self.al.append(2) self.al.append(3) self.al.append(4) with self.assertRaises(IndexError): self.al.remove(self.al.size()) def test_get__when_index_is_valid__expect_remove_values_and_return_it( self): self.al.append(1) self.al.append(2) self.al.append(33) self.al.append(4) result = self.al.get(2) self.assertEqual(33, result) def test_get__when_index_is_invalid__expect_remove_values_and_raise(self): self.al.append(1) self.al.append(2) self.al.append(3) self.al.append(4) with self.assertRaises(IndexError): self.al.get(self.al.size()) def test_extend_with_empty_iterable_expect_to_be_same(self): self.al.append(1) self.al.extend([]) self.assertEqual([1], list(self.al)) def test_extend__when_empty_with_not_empty_iterable__expect_to_be_same( self): self.al.extend([1]) self.assertEqual([1], list(self.al)) def test_extend_with_ist_expect_to_append_the_list(self): self.al.append(1) self.al.extend([2]) self.assertEqual([1, 2], list(self.al)) def test_extend_with_generator_expect_to_append_the_list(self): self.al.append(1) self.al.extend([x for x in range(1)]) self.assertEqual([1, 0], list(self.al)) def test_extend__with_not_iterable_expect_to_raise_valueError(self): self.al.append(1) with self.assertRaises(ValueError): self.al.extend(2) def test_insert__when_index_is_valid__expect_insert_values_at_index(self): self.al.append(1) self.al.append(2) self.al.append(4) self.al.append(5) self.al.append(6) self.al.append(7) self.al.append(8) self.al.append(9) self.al.insert(2, 33) self.assertEqual([1, 2, 33, 4, 5, 6, 7, 8, 9], list(self.al)) def test_insert__when_index_is_invalid__expect_insert_values_and_raise( self): self.al.append(1) self.al.append(2) self.al.append(4) with self.assertRaises(IndexError): self.al.insert(self.al.size() + 1, 2) def test_pop__expect_to_remove_last_element_and_remove_it(self): self.al.append(1) self.al.append(2) self.al.append(3) self.al.append(4) result = self.al.pop() self.assertEqual(4, result) self.assertListEqual([1, 2, 3], list(self.al)) def test_pop__when_empty_expect_raise(self): with self.assertRaises(IndexError): self.al.pop() def test_clear_expect_to_be_empy(self): [self.al.append(x) for x in range(15)] self.al.clear() self.assertEqual([], list(self.al)) def test_index__when_item_is_present__expect_to_return_correct_index(self): [self.al.append(x) for x in range(15)] index = self.al.index(5) self.assertEqual(5, index) def test_index__when_item_is_not_present__expect_to_raise(self): [self.al.append(x) for x in range(15)] with self.assertRaises(ValueError): self.al.index(17) def test_count__when_item_is_present__one_time_expect_to_return_1(self): [self.al.append(x) for x in range(15)] expected_count = 1 actual_count = self.al.count(5) self.assertEqual(expected_count, actual_count) def test_count__when_item_is_not_present__one_time_expect_to_return_0( self): [self.al.append(x) for x in range(15)] expected_count = 0 actual_count = self.al.count(55) self.assertEqual(expected_count, actual_count) def test_count__when_item_is_present__multiple_times_expect_to_return_correct_count( self): [self.al.append(x) for x in range(15)] self.al.append(5) self.al.insert(3, 5) self.al.insert(7, 5) self.al.insert(1, 5) self.al.insert(9, 5) expected_count = 6 actual_count = self.al.count(5) self.assertEqual(expected_count, actual_count) def test_count__when_item_is_present__multiple_times_and_once_poped_expect_to_return_correct_count( self): [self.al.append(x) for x in range(15)] self.al.insert(3, 5) self.al.insert(7, 5) self.al.insert(1, 5) self.al.insert(9, 5) self.al.append(5) self.al.pop() expected_count = 5 actual_count = self.al.count(5) self.assertEqual(expected_count, actual_count) def test_reverse__expect_in_reversed_order(self): [self.al.append(x) for x in range(5)] expected = [x for x in range(4, -1, -1)] actual = self.al.revers() self.assertEqual(expected, actual) def test_copy__expect_in_return_an_other_list_with_same_values(self): [self.al.append(x) for x in range(5)] copied_list = self.al.copy() expected_result = [x for x in range(5)] actual_result = list(copied_list) self.assertNotEqual(copied_list, self.al) self.assertEqual(expected_result, actual_result) def test_add_first__when_empty__expect_to_add(self): self.al.add_first(1) self.assertEqual([1], list(self.al)) def test_add_first__when_not_empty__expect_to_add(self): [self.al.append(x) for x in range(5)] self.al.add_first(1) self.assertEqual([1, 0, 1, 2, 3, 4], list(self.al)) def test_dictionize__when_empty__expect_empty_dict(self): actual = self.al.dictionize() expected = {} self.assertDictEqual(expected, actual) def test_dictionize__when_even_element_count__expect_empty_dict(self): self.al.append(1) self.al.append(2) self.al.append(3) self.al.append(4) actual = self.al.dictionize() expected = {1: 2, 3: 4} self.assertDictEqual(expected, actual) def test_dictionize__when_odd_element_count__expect_empty_dict(self): self.al.append(1) self.al.append(2) self.al.append(3) self.al.append(4) self.al.append(5) actual = self.al.dictionize() expected = {1: 2, 3: 4, 5: " "} self.assertDictEqual(expected, actual)
def test_insert_3(self): L = ArrayList() L.append( 1 ) L.insert( 0, np.arange(10), 1+np.arange(4) ) assert len(L) == 5 assert np.allclose(L[3], [6,7,8,9])
def test_insert_2(self): L = ArrayList() L.append( 1 ) L.insert( 0, np.arange(10), 2) assert len(L) == 6 assert np.allclose(L[4],[8,9])
def test_insert_1(self): L = ArrayList() L.append( 1 ) L.insert( 0, 2 ) assert len(L) == 2 assert L[0] == 2
class Collection(object): """ A collection is a container for several objects having the same vertex structure (vtype) and same uniforms type (utype). A collection allows to manipulate objects individually but they can be rendered at once (single call). Each object can have its own set of uniforms provided they are a combination of floats. """ def __init__(self, vtype, utype, itype=np.uint32): """ Parameters ---------- vtype: np.dtype Vertices data type utype: np.dtype Uniforms data type itype: np.dtype Indices data type """ vtype = np.dtype(vtype) if vtype.names is None: raise ValueError("vtype must be a structured dtype") utype = np.dtype(utype) if utype.names is None: raise ValueError("utype must be a structured dtype") itype = np.dtype(itype) if itype not in [np.uint8, np.uint16, np.uint32]: raise ValueError("itype must be unsigned integer or None") # Convert types to lists (in case they were already dtypes) such that # we can append new fields vtype = eval(str(np.dtype(vtype))) # We add a uniform index to access uniform data vtype.append(('a_index', 'f4')) vtype = np.dtype(vtype) # Check utype is made of float32 only utype = eval(str(np.dtype(utype))) r_utype = dtype_reduce(utype) if type(r_utype[0]) is not str or r_utype[2] != 'float32': raise RuntimeError( "Uniform type cannot be reduced to float32 only") count = int(math.pow(2, math.ceil(math.log(r_utype[1], 2)))) if (count - r_utype[1]) > 0: utype.append(('unused', 'f4', count - r_utype[1])) self._u_float_count = count # Create relevant array lists self._vertices = ArrayList(dtype=vtype) self._indices = ArrayList(dtype=itype) self._uniforms = ArrayList(dtype=utype) @property def u_shape(self): """ Uniform texture shape """ # max_texsize = gl.glGetInteger(gl.GL_MAX_TEXTURE_SIZE) max_texsize = 4096 cols = max_texsize // (self._u_float_count / 4) rows = (len(self) // cols) + 1 return rows, cols * (self._u_float_count / 4), self._u_float_count @property def vertices(self): """ Vertices buffer """ return self._vertices @property def indices(self): """ Indices buffer """ return self._indices @property def uniforms(self): """ Uniforms buffer """ return self._uniforms def __len__(self): """ """ return len(self._vertices) def __getitem__(self, key): """ """ V, U, I = self._vertices, self._uniforms, self._indices if V.dtype.names and key in V.dtype.names: return V[key] elif U.dtype.names and key in U.dtype.names: return U[key] else: return Item(self, key, V[key], I[key], U[key]) def __setitem__(self, key, data): """ """ # Setting vertices field at once if self._vertices.dtype.names and key in self._vertices.dtype.names: self._vertices.data[key] = data # Setting uniforms field at once elif self._uniforms.dtype.names and key in self._uniforms.dtype.names: self._uniforms.data[key] = data # Setting individual item else: vertices, indices, uniforms = data del self[key] self.insert(key, vertices, indices, uniforms) def __delitem__(self, key): """ x.__delitem__(y) <==> del x[y] """ if type(key) is int: if key < 0: key += len(self) if key < 0 or key > len(self): raise IndexError("Collection deletion index out of range") kstart, kstop = key, key + 1 # Deleting several items elif type(key) is slice: kstart, kstop, _ = key.indices(len(self)) if kstart > kstop: kstart, kstop = kstop, kstart if kstart == kstop: return elif key is Ellipsis: kstart, kstop = 0, len(self) # Error else: raise TypeError("Collection deletion indices must be integers") vsize = len(self._vertices[key]) del self._indices[key] self._indices[key] -= vsize del self._vertices[key] del self._uniforms[key] # Update a_index at once I = np.repeat(np.arange(len(self)), self._vertices.itemsize) self._vertices['a_index'] = I def insert(self, index, vertices, indices, uniforms=None, itemsize=None): """ Parameters ---------- index : int Index before which to insert data vertices : numpy array An array whose dtype is compatible with self.vertices.dtype indices : numpy array An array whose dtype is compatible with self.indices.dtype All index values must be between 0 and len(vertices) uniforms: numpy array An array whose dtype is compatible with self.uniforms.dtype itemsize: int or 1-D array If `itemsize is an integer, N, the array will be divided into elements of size N. If such partition is not possible, an error is raised. If `itemsize` is 1-D array, the array will be divided into elements whose succesive sizes will be picked from itemsize. If the sum of itemsize values is different from array size, an error is raised. """ # Make sure vertices/indices/uniforms are of the right dtype vtype = self._vertices.dtype vertices = np.array(vertices, copy=False).astype(vtype).ravel() itype = self._indices.dtype indices = np.array(indices, copy=False).astype(itype).ravel() utype = self._uniforms.dtype if uniforms is not None: uniforms = np.array(uniforms, copy=False).astype(utype).ravel() # Check index if index < 0: index += len(self) if index < 0 or index > len(self): raise IndexError("Collection insertion index out of range") # Inserting if index < len(self._vertices): vstart = self._vertices._items[index][0] istart = self._indices._items[index][0] ustart = self._uniforms._items[index][0] # Appending else: vstart = self._vertices.size istart = self._indices.size ustart = self._uniforms.size # Updating indices self._indices._data[istart:] += len(vertices) indices += vstart # Inserting one item if itemsize is None: #self._vertices[index:]['a_index'] += 1 #vertices['a_index'] = index self._vertices.insert(index, vertices) self._indices.insert(index, indices) if uniforms is not None: self._uniforms.insert(index, uniforms) else: U = np.zeros(1, dtype=self._uniforms.dtype) self._uniforms.insert(index, U) # Update a_index at once I = np.repeat(np.arange(len(self)), self._vertices.itemsize) self._vertices['a_index'] = I return # No item size specified if itemsize is None: v_itemcount = 1 v_itemsize = np.ones(1, dtype=int) * vertices.size i_itemcount = 1 i_itemsize = np.ones(1, dtype=int) * indices.size # Vertices size specified but no indices size if type(itemsize) is int: v_itemcount = vertices.size // itemsize v_itemsize = itemsize * np.ones(v_itemcount, dtype=int) i_itemcount = v_itemcount i_itemsize = len(indices) * np.ones(i_itemcount, dtype=int) indices = np.resize(indices, len(indices) * i_itemcount) # Vertices and indices size specified elif isinstance(itemsize, tuple): v_itemsize = itemsize[0] v_itemcount = vertices.size // v_itemsize v_itemsize = v_itemsize * np.ones(v_itemcount, dtype=int) i_itemsize = itemsize[1] i_itemcount = indices.size // i_itemsize i_itemsize = i_itemsize * np.ones(i_itemcount, dtype=int) # Vertices have different size else: itemsize = np.array(itemsize, copy=False) v_itemsize = itemsize[:, 0] i_itemsize = itemsize[:, 1] # Sanity check if (vertices.size % v_itemsize.sum()) != 0: raise ValueError("Cannot partition vertices data as requested") if (indices.size % i_itemsize.sum()) != 0: raise ValueError("Cannot partition indices data as requested") if v_itemcount != i_itemcount: raise ValueError("Vertices/Indices item size not compatible") I = np.repeat(v_itemsize.cumsum(), i_itemsize) indices[i_itemsize[0]:] += I[:-i_itemsize[0]] self._vertices.insert(index, vertices, v_itemsize) self._indices.insert(index, indices, i_itemsize) if uniforms is None: U = np.zeros(v_itemcount, dtype=self._uniforms.dtype) self._uniforms.insert(index, U, itemsize=1) else: if len(uniforms) != v_itemcount: if len(uniforms) == 1: U = np.resize(uniforms, v_itemcount) self._uniforms.insert(index, U, itemsize=1) else: raise ValueError( "Vertices/Uniforms item number not compatible") else: self._uniforms.insert(index, uniforms, itemsize=1) # Update a_index at once I = np.repeat(np.arange(len(self)), self._vertices.itemsize) self._vertices['a_index'] = I def append(self, vertices, indices, uniforms=None, itemsize=None): """ Parameters ---------- vertices : numpy array An array whose dtype is compatible with self.vertices.dtype indices : numpy array An array whose dtype is compatible with self.indices.dtype All index values must be between 0 and len(vertices) uniforms: numpy array An array whose dtype is compatible with self.uniforms.dtype itemsize: int, tuple or 1-D array If `itemsize is an integer, N, the array will be divided into elements of size N. If such partition is not possible, an error is raised. If `itemsize` is 1-D array, the array will be divided into elements whose succesive sizes will be picked from itemsize. If the sum of itemsize values is different from array size, an error is raised. """ self.insert(len(self), vertices, indices, uniforms, itemsize)
start = time.clock() for i in range(n): L.append(i) stop = time.clock() print("Array list, append %d items: %.5f" % (n, (stop - start))) L = ArrayList(dtype=int) start = time.clock() L.append(range(n), 1) stop = time.clock() print("Array list, append %d items at once: %.5f" % (n, (stop - start))) L = [] start = time.clock() for i in range(n): L.insert(0, i) stop = time.clock() print("Python list, prepend %d items: %.5f" % (n, (stop - start))) L = ArrayList(dtype=int) start = time.clock() for i in range(n): L.insert(0, i) stop = time.clock() print("Array list, prepend %d items: %.5f" % (n, (stop - start))) L = ArrayList(dtype=int) start = time.clock() L.append(range(n, 0, -1), 1) stop = time.clock() print("Array list, append %d items at once: %.5f" % (n, (stop - start)))