8

I am teaching the A level syllabus by the Cambridge exam board. One typical question on the practical paper is this:

In a programming language of your choice, declare an array of ten integers and then initializes it.

I have this:

myArray = []        #create the array

for i in range(10): # initializes to 0
    myArray.append(0)

I believe this is what most people would do in Python? However, unlike Pascal etc it does not strictly answer the question as the lists in Python are essentially dynamic arrays with the added problem of not restricting the data type of each element. Can I declare a specific size array and type like in Pascal, instead of an empty dynamic list, without any type of loop and restricts the type of the array?

Something like (pseudo code):

myArray[10] : integer

This is a none commercial question but an educational one.

James Bradbury
  • 1,708
  • 1
  • 19
  • 31
Timothy Lawman
  • 2,194
  • 6
  • 24
  • 33
  • 1
    check this http://stackoverflow.com/questions/5944708/python-forcing-a-list-to-a-fixed-size & http://stackoverflow.com/questions/521674/initializing-a-list-to-a-known-number-of-elements-in-python – avasal Oct 22 '12 at 11:28

6 Answers6

11

You could try to use the array module to specify the type of your array:

import array
a = array.array('i') # Define an integer array.

You can then add the elements you want to the array. I'm not sure whether you can predefine the size your array should have, though. If you want an array of ten integer elements, each element being zero, you could do:

a = array.array('i', [0]*10)

As described in the documentation, the 'i' forces the elements of the array to be integers. Python 2.6 will throw a DeprecationWarning if you try to insert a float in an array of integers, but will cast the float as an int:

>>> a[0]=3.14159
>>> a
>>> array('i', [3, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Alternatively, you could use the numpy package, which lets you define both the size and the type of the array.

import numpy as np
a = np.empty(10, dtype=int) # Define a integer array with ten elements

The np.empty just reserves some space in memory for the array, it doesn't initialize it. If you need an array of 0, you could do:

a[:] = 0

or directly use the np.zeros function:

a = np.zeros(10, dtype=int)

Here again, inserting a float in an array of integers will silently convert the float to integer.

Note a difference between numpy and array: once you define an array in numpy, you cannot change its size without having to recreate an array. In that sense, it satisfies your requirement of "10 and only 10 integers". By contrast, a array.array object can be seen as a list with a fixed element type: the array is dynamic, you can increase its size.

Pierre GM
  • 19,809
  • 3
  • 56
  • 67
  • This was a solution I thought of but numpy is not part of the chosen language which is Python but an added module perhaps written in C which is a different language. However, I will offer this one to candidates as well. – Timothy Lawman Oct 22 '12 at 11:40
  • Apologies, you are correct. My final question is: does the 'i' variable actually restrict the array to integers and give an error if another type is appended and is the array module written in Python and not C?. If so this would be the perfect answer? Oh well I shall fire up the shell:) – Timothy Lawman Oct 22 '12 at 11:52
  • @pythonMan True, numpy is an additional dependence. However, it's common enough a package (especially in scientific fields). For your second question: `array` will complain if you try to add a `float` to an `int` array, while `numpy` will silently cast your float to an int. – Pierre GM Oct 22 '12 at 11:53
  • @pythonMan Yes, as I stated in a comment elsewhere the `'i'` in the array does restrict it to `int`s only. – Matt Oct 22 '12 at 11:54
  • Nearly there. Unfortunately, it passes all parts of the question except one: it is not fixed at 10 integers but is still a dynamic array that allows overflow, although it disallows none integers! – Timothy Lawman Oct 22 '12 at 11:56
  • @pythonMan: the `np.empty` version (i) forces the array to have 10 elements *and only 10* and (ii) forces each element to be an integer. – Pierre GM Oct 22 '12 at 12:00
  • Looks like numpy is the only real solution although it is not part of Python but a module.Thanks. – Timothy Lawman Oct 22 '12 at 12:38
  • @pythonMan As I stated in my answer you can use ctypes to get exactly what you want. You can make a fixed length and integer only array. – Matt Oct 22 '12 at 14:17
7

You could use the array module

a = array.array('i',(0 for _ in xrange(10)))

Arrays require that all elements be the same type, as specified when it is created. They can still be appended to however

If you were really determined, you could use the ctypes module to build a C array. But, that is probably not very pythonic as it forces you to do more low level stuff.

import ctypes
intArray10 = ctypes.c_int * 10
myArray = intArray10(*(0 for _ in xrange(10)))
Matt
  • 3,651
  • 3
  • 16
  • 35
  • I think as in the answer above ,it solves only partially the problem. This has a loop which I am trying to omit.Also, if I append a none int will it fail as expected as well as prevent a.append() statements? – Timothy Lawman Oct 22 '12 at 11:38
  • @pythonMan There is no loop in the code I posted. It contains a generator expression which I specifically chose for this example so a full list never exists in memory until you have created the array. If you try to append `None` to this array you will get an error as `None` is of type `NoneType` and is therefore not an `int` – Matt Oct 22 '12 at 11:44
  • @pythonMan The array module example will allow you to append. If you don't want to allow appending then use an array from ctypes. – Matt Oct 22 '12 at 11:46
  • 1
    You make a valid point. C is not the chosen language, so it would fail in the exam question if you had stated that Python was your chosen language. I think Python simply does not have built in fixed arrays in its core without importing or work arounds. – Timothy Lawman Oct 22 '12 at 14:27
  • @pythonMan Why would it fail the exam question? ctypes is part of the standard library, and this is therefore a valid python program. It also meets the requirements (which is better than any other solution I have seen posted here). – Matt Oct 22 '12 at 14:33
  • I would really like to vote for matt's answer:how can I do this? – Timothy Lawman Oct 23 '12 at 09:59
6

This is a more pythonic way to initialize the list:

>>> l = [0] * 10
>>> l
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> l[1] = 1
>>> l
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0]

This, of course, does not answer the question how to create such an un-pythonic thing as a list of restricted elements.

  • Thanks for your reply. This answers two thirds of the question but you can still add none integers.Is there a way to prevent anything other than integers. Also you can append another integer without an overflow error so strictly it is not a fixed array? – Timothy Lawman Oct 22 '12 at 11:34
  • @pythonMan Yes, you can append another integer or any other object for that matter. `l` is a regular Python list with no special limitations. – phant0m Oct 22 '12 at 11:57
2

As has already been mentioned l = [0] * 10 initializes a list with 10 zeros.

While it is possible to add more elements, you cannot do so by mistake.

>>> l = [0] * 10
>>> l[10] = 1

Traceback (most recent call last):
    l[10] = 1
IndexError: list assignment index out of range

If you want to append to the list, you need to call .append() or some other method that adds new elements. Thus, you cannot add elements by accident, you need to be explicit about it.

In many other languages, you could just replace the array with one that has a different size. Point being, you can often find a way around such limitations, and I think it's good to just use the easiest thing that works and is well understood.

For me, that would be

>>> l = [0] * 10
phant0m
  • 16,595
  • 5
  • 50
  • 82
0
class myTypedArray:

    def __init__(self,mytype):
        self._internalList =    []
        self._internalType =    mytype

    def add(self,x):
       if type(x) == self._internalType:
            self._internalList.append(x)
       #else raise an Error to warn User of typedArray                                                   

    def __str__(self):
       s = ""
       for x in self._internalList:
            s+=str(x)
       return s


x = myTypedArray(int)

x.add(1)
x.add("xyz") # will not be added

print x # output: 1

If you want to restrict the size, you can track the size and throw an exception. So extending types in Python is very easy as you can see. The whole point of the static typed languages such as C, is to be closer to hardware. This example myTypedArray is not efficient, so there is usually no reason to use static types.

RParadox
  • 6,393
  • 4
  • 23
  • 33
  • I am afraid as it is an education question and not a practical one that I was looking for built in Python commands rather than work arounds and class definitions. – Timothy Lawman Oct 22 '12 at 11:49
  • Well it's not possible to implement using built-in types. This solutions works. You can add maxsize to the definition and check with each addition if maxsize is reached. Builtin types __are__ dynamic, so you have to override the methods yourself. If you want to create your own types, you will have to use class. That's what it is there for. – RParadox Oct 22 '12 at 12:08
  • Yes, I get this, but the original question is not about creating your own types; it is about using the original built in features of the language. You only have space for 3-4 lines of code on the paper. Classes do not appear on this paper anyway. I appreciate you are correct in everything you say but the question addresses built in arrays not classes. – Timothy Lawman Oct 22 '12 at 14:25
  • Then the answer is, it is not possible. Python builtin types are dynamic by nature. – RParadox Oct 22 '12 at 14:59
  • phantOm: I received an answer from the exam board which was that my initial solution was fine as long as the student commented why he had used a dynamic array. A teacher then commenting on it on te discussion thread said that it did not answer the question as I also proposed to stackflow's audience. Therefore to conclude: my way is fine but it is still causing controversy amongst teachers! – Timothy Lawman Nov 01 '12 at 12:03
0

You can do it using array module. array module is part of python standard library:

from array import array
from itertools import repeat

a = array("i", repeat(0, 10))
# or
a = array("i", [0]*10)

repeat function repeats 0 value 10 times. It's more memory efficient than [0]*10, since it doesn't allocate memory, but repeats returning the same number x number of times.

Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179