[Tutor] Making Doubly Linked List with Less Lines of Code.
Alan Gauld
alan.gauld at btinternet.com
Fri Jan 2 02:35:48 CET 2015
On 02/01/15 01:03, Alex Kleider wrote:
> I don't think I understand the distinction between 'copies' and 'repeats'.
copy creates a new object with the same attributes as the original
original = [1,2,3]
copy = original[:] # slicing creates a copy
copy == original -> True
copy is original -> False
Repeats replicates the reference to the object but
does not create a new object.
reference = original # both refer to same object
reference = original -> True
reference is original -> True
> I think I understand the difference between copy and deep copy and I
> think that is the issue here but it isn't yet clear.
Deep copy is not an issue here.
>>>> s_grid = [[0]*5 for i in range(4)]
> # So for each iteration of the list comprehension,
> # a brand new, ?immutable? object ( a list of zeros) is created.
> # Immutable by virtue of the fact that there is no reference to it
> # and therefore it can't be changed?????
It's not immutable. Whether a reference to it exists or not
has no bearing on whether it has the potential to be changed.
In fact each object created has a reference:
s_grid[0], s_grid[1], etc...
You have 5 objects, each a list of 5 zeros.
All 5 lists are mutable and all 5 are equal but not
identical (ie. not the same object).
>>>> s_grid
> [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>>> s_grid[1][1] = 99
>>>> s_grid
> [[0, 0, 0, 0, 0], [0, 99, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] #
And as expected changing one object has no impact on the others.
And by changing it you demonstrate that the objects are not
immutable - you just mutated it!
>>>> l = [0]*5
>>>> l
> [0, 0, 0, 0, 0]
You now have one list object containing 5 zeros and
a reference to it from 'l'
>>>> grid = [l for i in range(4)]
Now you have 4 more references to the same object 'l'
refers to.
> # In this form, the list comprehension is encountering a mutable
> # object by virtue of the fact that there is a reference to it?
No, the reference is irrelevant.
It is mutable by virtue of being a list.
>>>> grid[1][1] = 99
>>>> grid
> [[0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0]]
You modified the object so all references (including the original 'l')
will reflect the change
> # Is the crux of the matter that l is mutable (because it is a reference,)
No the objects are mutable in both examples.
mutable means you can change them. It has nothing to do with
whether there is a reference or not. (Although, if there
were truly no references the object would be destyroyed
by the garbage collector)
> # while [0]*5 is not (because it is an expression?)
[0]*5 is an expression that yields a list object.
The list object is mutable. You proved that by
changing one of them.
>>>> my_grid = [[0, 0, 0, 0] for i in range(4)]
>>>> my_grid
> [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Now you have created another list of 5 objects. Again each object has 4
zeros and they are equal but not identical. They are all mutable.
They are all referenced via my_grid. (my_grid[0],...)
>>>> my_grid[1][1] = 99
>>>> my_grid
> [[0, 0, 0, 0], [0, 99, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Again you changed(mutated) one of the objects. The
others remain untouched.
>>>> another_grid = [[0]*5]*4
Here you create a list of 4 references to the list produced by [0]*5
One list object, 4 references.
> # The explanations above don't seem to explain things here.
>>>> another_grid
> [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>>> another_grid[1][1] = 99
>>>> another_grid
> [[0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0], [0, 99, 0, 0, 0]]
Again there is only one list object, so when you change it via
any of the references all the references reflect that change.
> My interpretation is that we appear to be getting a deep copy at the
> inner level of a multiplication but a not deep copy at the outer level.
No copying is going on at any point.
> List comprehension provides us with a deep copy but only if we give it a
> literal (as opposed to a reference.)
No, list comprehensions (and generator expressions in general)
return a sequence made up of whatever object the first
expression evaluates to. That could be an existing object
(like the one referenced by 'l' above) or a newly created
(possibly literal) object like [0, 0, 0, 0].
HTH
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos
More information about the Tutor
mailing list