views:

528

answers:

4

Hi all,

I'm a looking to initialize an array/list of objects that are not empty -- the class constructor generates data. In C++ and Java I would do something like this:

Object lst = new Object[100];

I've dug around, but is there a Pythonic way to get this done? This doesn't work like I thought it would(I have 100 references to the same object):

lst = [Object()]*100

But this seems to:

lst = [Object() for i in range(100)]

List comprehension seems (intellectually) like "a lot" of work for something that's so simple in Java.

Thanks!

+5  A: 

There isn't a way to implicitly call an Object() constructor for each element of an array like there is in C++ (recall that in Java, each element of a new array is initialised to null for reference types).

I would say that your list comprehension method is the most Pythonic:

lst = [Object() for i in range(100)]

If you don't want to step on the lexical variable i, then a convention in Python is to use _ for a dummy variable whose value doesn't matter:

lst = [Object() for _ in range(100)]

For an equivalent of the similar construct in Java, you can of course use *:

lst = [None] * 100
Greg Hewgill
+1. I would suggest xrange instead of range.
orip
Fair point; I've been coding in Python 3 recently. :)
Greg Hewgill
A: 
lst = [Object() for i in range(100)]

Since an array is it's own first class object in python I think this is the only way to get what you're looking for. * does something crazy.

Paul Huff
+1  A: 

I think the list comprehension is the simplest way, but, if you don't like it, it's obviously not the only way to obtain what you desire -- calling a given callable 100 times with no arguments to form the 100 items of a new list. For example, itertools can obviously do it:

>>> import itertools as it
>>> lst = list(it.starmap(Object, it.repeat((), 100)))

or, if you're really a traditionalist, map and apply:

>>> lst = map(apply, 100*[Object], 100*[()])

Note that this is essentially the same (tiny, both conceptually and actually;-) amount of work it would take if, instead of needing to be called without arguments, Object needed to be called with one argument -- or, say, if Object was in fact a function rather than a type.

From your surprise that it might take "as much as a list comprehension" to perform this task, you appear to think that every language should special-case the need to perform "calls to a type, without arguments" over other kinds of calls to over callables, but I fail to see what's so crucial and special about this very specific case, to warrant treating it differently from all others; and, as a consequence, I'm pretty happy, personally, that Python doesn't single this one case out for peculiar and weird treatment, but handles just as regularly and easily as any other similar use case!-)

Alex Martelli
I feel that you are overcomplicating things. Something as simple as this will NOT require the import of other modules
inspectorG4dget
Good point about the special case -- I guess I hadn't thought about it from that point of view. That map line is really neat -- I haven't played with maps yet, so I'll have to play with it.
bgt421
Ah but @Inspector, you see, the map/apply solution doesn't require any import, but that doesn't make it any less complicated than the itertools one: it just happens to use old stuff which happened to be placed in builtins many, many years ago, while itertools is a newer idea and was properly put in its own module of the standard library. `apply` is gone in Python 3, and `map` changed. So, you see: your perceptions of what's complicated (based on such a totally inappropriate criterion as using import or not!) are really entirely, fundamentally wrong and misplaced.
Alex Martelli
+9  A: 

You should note that Python's equvalent for Java code (creating array of 100 null references to Object):

Object arr = new Object[100];

or C++ code:

Object **arr = new Object*[100];

is:

arr = [None]*100

not:

arr = [Object() for _ in range(100)]

The second would be the same as Java's:

Object arr = new Object[100];
for (int i = 0; i < arr.lenght; i++) {
    arr[i] = new Object();
}

In fact Python's capabilities to initialize complex data structures are far better then Java's.


Note: C++ code:

Object *arr = new Object[100];

would have to do as much work as Python's list comprehension:

  • allocate continuous memory for 100 Objects

  • call Object::Object() for each of this Objects

And the result would be a completely different data structure.

Tomek Szpakowicz