Python does not have a native "array" type, although it has several native types, nor does it have its default library.
numpy
For any serious work involving arrays (that is, you have a problem involving "real-world" arrays) the ideal is to install a separate module that has not only the arrays, but high-performance code for operations on the elements and between the matrices. The most famous for this is by numpy . It is automatically installed in the scientific distributions of Python like Anaconda and others.
With numpy installed, you have a number of tools for creating arrays - one of the most practical is np.zeros
, for which you pass only the desired sizes in each dimension and the data types:
In [2]: np.zeros((4,4), dtype=np.float64)
Out[2]:
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
And a cool thing about these arrays is that they are objects that make use of methods that use indexes on an object (that is, the class methods that are called when we use brackets after the object) - and use tuples in indexes to address the elements - then a[0,0]
will address the element in the zero line, zero column of array "a". More importantly, it supports the use of Python slices in these indexes too, so you can do that:
In [3]: a = np.zeros((5,5), dtype=np.float64)
In [4]: a[1:4, 1:4] = 1
In [5]: a
Out[5]:
array([[ 0., 0., 0., 0., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 1., 1., 1., 0.],
[ 0., 0., 0., 0., 0.]])
And these arrays already work very well with a whole series of operations defined for arrays in mathematics - they are not just arrays of dumb objects - you can add them to each other, or perform any other operation. In fact, the numpy project is and its array processing is so important to Python that during version 3.5 development they requested that a new operator be added to the language - the @
that is used for matrix multiplier. (It is not used in normal Python - any object can implement the __matmul__
method and do something with the "@" operator - but it was created at the request of the numpy staff.
In [6]: a = np.array([[1,2,3], [4,5,6], [7,8,9]], dtype=np.float)
In [7]: a
Out[7]:
array([[ 1., 2., 3.],
[ 4., 5., 6.],
[ 7., 8., 9.]])
In [8]: b = np.array([2,2,2])
In [10]: a@b
Out[10]: array([ 12., 30., 48.])
Now for very short projects, or for teaching purposes, you may want to create your own "multidimensional arrays" - and then you can create lists where each element is a list - with some care -
or - a little better, implement your own class that treats the indexes in a numpy-like way - or even use a dictionary directly.
update : I just discovered the tinynumpy project: it has the same facilities as numpy arrays For simian things, but its installation is much smaller and it is in pure Python: it can be worth in environments with restrictions on installing binary files or with limited disk space.
lists of lists
Just use standard Python code to create multiple lists within an initial list, and address each element with brackets in a row:
In [17]: m = []
In [18]: for y in range(4):
...: linha = []
...: for x in range(4):
...: linha.append(0)
...: m.append(linha)
...:
In [19]: m
Out[19]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
In [20]: m[0][0] = 5
In [21]: m
Out[21]: [[5, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Or on a single line:
In [22]: n = [[0] * 4 for i in range (4)]
In [23]: n
Out [23]: [[0, 0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
And taking some care - for example, if I multple a same object "list" in trying to get multiple rows from the array, I will actually have copies of the same starting line on all rows, and many bugs:
In [25]: o = [[0] * 4] * 4
In [26]: o
Out[26]: [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
In [27]: o[0][0] = 1
In [28]: o
Out[28]: [[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
This form is the simplest way to create a Python array, as it is in the other answers, but it will work harder: arrays of this type do not take advantage of object-oriented capabilities at all - has to be done by addressing each element of the array with external code that uses the two sets of brackets.
dict
You can use simple dictionaries in Python as arrays. Since tuples can be used inside the and brackets can be dictionary keys, you only need a defaultdict that returns the initial value for each element that has not yet been used - and with a minimal sophistication, checks the boundaries of the array.
Normal dictionaries have the .setdefault
method that can be used in place of the brackets to provide the initial value. It's cool why you do not need to build a special object - but it's bad why it will not work with the bracket syntax for reading:
In [29]: m = dict()
In [30]: m.setdefault((0,0), 0)
Out[30]: 0
In [31]: m[0,0] = 1
In [32]: m.setdefault((0,0), 0)
Out[32]: 1
In [33]: m.setdefault((4,4), 0)
Out[33]: 0
custom dict
The dictionary class project now prevents subclasses from having the __missing__
method that would be automatically called for a non-existent index.
class M(dict):
def __init__(self, dimensions, default=0):
self.dimensions = dimensions
self.default = default
def _convert(self, index):
if not hasattr(self, '__len__'):
raise IndexError('Use a sequence as index for matrices')
if len(index) != len(self.dimensions):
raise IndexError("Incorrect index dimentsions")
for d, i in zip(self.dimensions, index):
if i < 0 or i >= d:
raise IndexError("Index out of range")
return tuple(index)
def __missing__(self, index):
index = self._convert(index)
return self.get(tuple(index), self.default)
def __setitem__(self, index, value):
index = self._convert(index)
return super().__setitem__(index, value)
def __repr__(self):
if len(self.dimensions) == 2:
result = "[{}]".format("\n".join(", ".join(str(self[i, j]) for j in range(self.dimensions[1])) for i in range(self.dimensions[0])))
else:
result = "<matrix {} >".format(super().__repr__())
return result
custom class
Or, finally, create your own class that implements the methods __getitem__
, __setitem__
and __delitem__
to have an array type completely under your control - I usually create such classes to keep representations in memory which is on the screen of simple games in the style of snake, tetris, "candycrush saga", for example.