314

I would like to know how i can initialize an array(or list), yet to be populated with values, to have a defined size.

For example in C:

int x[5]; /* declared without adding elements*/

How do I do that in Python?

10
  • 4
    All of these: stackoverflow.com/search?q=%5Bpython%5D+array+of+fixed+size. Commented May 26, 2011 at 17:38
  • 1
    possible duplicate of Python, forcing a list to a fixed size Or maybe this: stackoverflow.com/questions/4056768/… Commented May 26, 2011 at 17:38
  • 3
    The more interesting question is why you want to do this. Most of the situations where I've seen this needed are because of bad decisions. Commented May 26, 2011 at 17:40
  • 3
    You almost never need this. In 99% of the cases you can generate the values in one swoop, e.g. using a list comprehension, or you simply start with [] and .append() or .expand() in a while loop or something like that (lists are over-allocating so resizing is amortized O(1)). Commented May 26, 2011 at 17:41
  • 3
    You should explain your motivation for needing this. Performance? Security? Interfacing with C/C++/NumPy/...? Commented Feb 9, 2012 at 23:25

11 Answers 11

449

You can use:

>>> lst = [None] * 5
>>> lst
[None, None, None, None, None]
Sign up to request clarification or add additional context in comments.

8 Comments

The question specified ".. yet to be populated with values". The Python docs indicate "None is typically used to represent absence of a value". My example produced such a list of the defined size, in the shortest amount of code. Its the closest thing in idiomatic Python at the time the question was asked.
This meets the requirements of the question because you have a defined size array and you can index one of the five elements without getting an IndexError. This is the closest thing to the C expression.
@user2233706 It would be closer to C if the array were populated with zeros.
You can do lst = [0] * 5 is you want >>> [0]*5 [0, 0, 0, 0, 0]
One thing to note: all elements in the list will have initially the same id (or memory address). When you change any element later on in the code, this will impact only the specified value, - HOWEVER - if you create a list of custom objects in this way (using the int multiplier) and later on you change any property of the custom object, this will change ALL the objects in the list.
|
112

Why don't these questions get answered with the obvious answer?

a = numpy.empty(n, dtype=object)

This creates an array of length n that can store objects. It can't be resized or appended to. In particular, it doesn't waste space by padding its length. This is the Python equivalent of Java's

Object[] a = new Object[n];

If you're really interested in performance and space and know that your array will only store certain numeric types then you can change the dtype argument to some other value like int. Then numpy will pack these elements directly into the array rather than making the array reference int objects.

6 Comments

If it had been that obvious, though, someone else would have provided this.. again, importing a library just to get this functionality may not be the best option.
Except that this is the only answer here which is actually correct. The OP didn't specify that module loading was prohibited. Nor did he ask for a list. The question is very specific and this answer is correct. +1
adding a large module such as numpy is an unnecessary overhead
Can you explain why the choice of dtype=object as opposed to some other dtype?
They said Python, not Python + Numpy. Numpy is not a trivial add-on, either. It can't be uninstalled and therefore is highly problematic for embedded Python uses.
|
69

Do this:

>>> d = [ [ None for y in range( 2 ) ] for x in range( 2 ) ]
>>> d
[[None, None], [None, None]]
>>> d[0][0] = 1
>>> d
[[1, None], [None, None]]

The other solutions will lead to this kind of problem:

>>> d = [ [ None ] * 2 ] * 2
>>> d
[[None, None], [None, None]]
>>> d[0][0] = 1
>>> d
[[1, None], [1, None]]

4 Comments

Good answer. The problem you mention screwed me up at a programming competition. Do you know the exact mechanics under the bonnet to cause this?
Python copies "plain old data types" by value, and the rest by reference, and it's not always clear when one or the other is happening.
in case anyone wondering, the behavior is (TLDR first multiplier creates n length array, second multiplier creates a list of the arrays of m length by copying the first array by reference) explained here docs.python.org/2/faq/…
I had the exact problem.
17

The best bet is to use the numpy library.

from numpy import ndarray

a = ndarray((5,),int)

2 Comments

and would it be best?
It's not really the best to have to import a library just to use an array. Other ways exist.
14

An easy solution is x = [None]*length, but note that it initializes all list elements to None. If the size is really fixed, you can do x=[None,None,None,None,None] as well. But strictly speaking, you won't get undefined elements either way because this plague doesn't exist in Python.

2 Comments

For most C use cass of an array, a normal (non-fixed) list is the idiomatic python equivalent. This is an answer to the question, as it probably helps the the OP (who is transitting from C to Python) most.
if you're gonna write all the elements anyways, then it's not a plague -- it's just saving you a double write to the same memory.
14
>>> import numpy
>>> x = numpy.zeros((3,4))
>>> x
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])
>>> y = numpy.zeros(5)   
>>> y
array([ 0.,  0.,  0.,  0.,  0.])

x is a 2-d array, and y is a 1-d array. They are both initialized with zeros.

1 Comment

You should provide a kind of explanation ...
13
>>> n = 5                     #length of list
>>> list = [None] * n         #populate list, length n with n entries "None"
>>> print(list)
[None, None, None, None, None]

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[None, None, None, None, 1]

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[None, None, None, 1, 1]

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[None, None, 1, 1, 1]

or with really nothing in the list to begin with:

>>> n = 5                     #length of list
>>> list = []                 # create list
>>> print(list)
[]

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[1]

on the 4th iteration of append:

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[1,1,1,1]

5 and all subsequent:

>>> list.append(1)            #append 1 to right side of list
>>> list = list[-n:]          #redefine list as the last n elements of list
>>> print(list)
[1,1,1,1,1]

Comments

3

Well I would like to help you by posting a sample program and its output

Program:

t = input("")
x = [None]*t
y = [[None]*t]*t

for i in range(1, t+1):
    x[i-1] = i;

    for j in range(1, t+1):
        y[i-1][j-1] = j;

print x
print y

Output :-

2
[1, 2]
[[1, 2], [1, 2]]

I hope this clears some very basic concept of yours regarding their declaration. To initialize them with some other specific values, like initializing them with 0.. you can declare them as:

x = [0]*10

Hope it helps..!! ;)

6 Comments

Your code doesn't define fixes-size array/list as requested in question. You just put some values in list, which still can be of any length
and why is it -1 while the +12 answer states the same way of doing so?
@lejlot because +12 answer is wrong too and similarly doesn't answer original question
I would not call them wrong, python simply does not have such low level access to memory management, while provided answers are really close to the expected behavior from the practical point of view
This solution does not do what you expect it to. [[None] * t] * t will create a list of t copies of the same "row". See this question in the Python FAQ.
|
2

You can try using Descriptor, to limit the size

class fixedSizeArray(object):
    def __init__(self, arraySize=5):
        self.arraySize = arraySize
        self.array = [None] * self.arraySize

    def __repr__(self):
        return str(self.array)

    def __get__(self, instance, owner):
        return self.array

    def append(self, index=None, value=None):
        print "Append Operation cannot be performed on fixed size array"
        return

    def insert(self, index=None, value=None):
        if not index and index - 1 not in xrange(self.arraySize):
            print 'invalid Index or Array Size Exceeded'
            return
        try:
            self.array[index] = value
        except:
            print 'This is Fixed Size Array: Please Use the available Indices'


arr = fixedSizeArray(5)
print arr
arr.append(100)
print arr
arr.insert(1, 200)
print arr
arr.insert(5, 300)
print arr

OUTPUT:

[None, None, None, None, None]
Append Operation cannot be performed on fixed size array
[None, None, None, None, None]
[None, 200, None, None, None]
This is Fixed Size Array: Please Use the available Indices
[None, 200, None, None, None]

1 Comment

What point does your def __get__(self, instance, owner): have in this context? Instead, you should define __(set|get|del)item__(), the latter setting it/them to None.
2

One thing I find easy to do is i set an array of empty strings for the size I prefer, for example

Code:

import numpy as np

x= np.zeros(5,str)
print x

Output:

['' '' '' '' '']

Hope this is helpful :)

Comments

0

If you are working with bytes you could use the builtin bytearray. If you are working with other integral types look at the builtin array.

Specifically understand that a list is not an array.

If, for example, you are trying to create a buffer for reading file contents into you could use bytearray as follows (there are better ways to do this but the example is valid):

with open(FILENAME, 'rb') as f:
    data = bytearray(os.path.getsize(FILENAME))
    f.readinto(data)

In this snippet the bytearray memory is preallocated with the fixed length of FILENAMEs size in bytes. This preallocation allows the use of the buffer protocol to more efficiently read the file into a mutable buffer without an array copy. There are yet better ways to do this but I believe this provides one answer to your question.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.