# Multi-dimensional list initialization

Andrew Robinson andrew3 at r3dsolutions.com
Thu Nov 8 00:55:30 CET 2012

```On 11/07/2012 05:39 AM, Joshua Landau wrote:
>
>
> On 7 November 2012 11:11, Oscar Benjamin wrote:
>
>     On Nov 7, 2012 5:41 AM, "Gregory Ewing"  wrote:
>     >
>     > If anything is to be done in this area, it would be better
>     > as an extension of list comprehensions, e.g.
>     >
>     >   [[None times 5] times 10]
>     >
>     > which would be equivalent to
>     >
>     >   [[None for _i in xrange(5)] for _j in xrange(10)]
>
Oscar, I'm really in agreement with you;  I think that it's better to
group all *special* array/list constructions into a single logical unit
which will show up in the same part of the Python documentation.
>
>     A multidimensional list comprehension would be useful even for
>     people who are using numpy as it's common to use a list
>     comprehension to initialise a numpy array.
>
I hadn't paid that much attention; but I think that's true of people
using the newer releases of Numpy.
A Very interesting point... Thank you for mentioning it.

>     A more modest addition for the limited case described in this
>     thread could be to use exponentiation:
>
>     >>> [0] ** (2, 3)
>     [[0, 0, 0], [0, 0, 0]]
>
I'm against over using the math operators, for the reason that matrix
and vector algebra have meanings mathematicians desire (rightly) to
maintain.  Numpy users might find matricies overloaded to do these
things in the future -- and then it becomes unclear whether an
initialization is happening or a mathematical operation. I think it best
just not to set up an accident waiting to happen in the first place.

> Hold on: why not just use multiplication?
> >>> [0] * (2, 3)
Would you consider that better than [0].nest(2).nest(3) ? or [0].nest(2,3) ?
(I'm against multiplication, but I'm still interested in what you find
> We do have to think of the potential problems, though. There are
> definitely some. For one, code that relies on lst * x throwing an
> error would break. It may confuse others - although I don't see how.
Excellent observation:
People relying on an exception, would be in the try: operation.
So, since lst * int  does not cause an exception; they would need a
reason to be concerned that someone passed in a list instead of an
integer.  Semantically, the same KIND of result happens, lst is in some
way duplicated; so if the result is accepted, it likely would work in
place of an integer.
So, the concern would be where someone wanted to detect the difference
between an integer and a list, so as to run some alternate algorithm.

Eg, say a vector multiply, or similar operation.  The design would want
to shadow * and call a method to do the multiply; You'd have a fragment
possibly like the following:

...
try: ret = map( lambda x: x*rightSide, leftSide )
except TypeError:  for i in rightSide: self.__mul__( rightSide, i )
# recursive call to __mul__
...

That's a common technique for type checking dating from earlier releases
of Python, where the "type" attribute wasn't available.  It also works
based on functionality, not specific type -- so objects which "work"
alike (subclasses, alternate reinventions of the wheel) also can be handled.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20121107/09558ba1/attachment.html>
```