[Tutor] filling 2d array with zeros

Steven D'Aprano steve at pearwood.info
Tue Sep 28 02:46:20 CEST 2010


On Tue, 28 Sep 2010 06:00:41 am Alex Hall wrote:
> > [ [0]*3 ]*4 behaves the same way. There's no problem in the inner
> > list, but the outer list doesn't make four copies of [0,0,0], it
> > has *one* list repeated four times. Modify one, modify them all.
>
> That makes sense. Basically, the * operator in this case acts as a
> copying command. For simple data types this is fine, but throw in a
> complex type, in this case a list (though I expect that any object
> would do this) and you are just doing what Python does to copy
> objects: copying the memory location, not making a deep copy and
> getting a duplicate object. I never would have thought of that.
> Thanks again for the great explanation!

No, be careful about your terminology. I get that you understand what is 
going on, but you're saying it wrong. The * operator doesn't make 
copies. I know it's tempting to say it does, sometimes I catch myself 
saying so myself, but what Python is doing is making multiple 
references to the same object. The object is not copied.

It may be easier if you think about the underlying C implementation 
(under the hood, in the engine) rather than the Python level. At the 
Python level, objects can be in multiple places at once. Objects like 
lists can even be inside themselves:

>>> L = []
>>> L.append(L)

If you've watched Doctor Who as a child, and seen his TARDIS (which of 
course is bigger on the inside than the outside) land inside itself, 
such strange loops won't hold any fear for you at all :)

But at the C level, Python doesn't make copies of any object unless 
necessary. The *name* L is a pointer to the list object. When you 
execute:

L = []

Python creates a name L which then points ("refers to") to a list 
object. When you next do this:

L.append(L)

Python doesn't move the list object into itself -- that would be a good 
trick. Besides, objects are big, complex chunks of memory and moving 
them around would be slow, so Python leaves the list where it is and 
simply places a pointer to L into the appropriate list position.

(But don't forget that Python is not necessarily written in C. There's 
Jython, written in Java, and CLPython written in Lisp, and many others. 
How they implement objects may be different. What happens under the 
hood isn't important, so long as the behaviour at the Python level 
remains the same.)

So at the Python level, there is never any copying of objects unless you 
specifically ask for it, and the * operator doesn't make any copies at 
all. It repeats the one object multiple times.


-- 
Steven D'Aprano


More information about the Tutor mailing list