Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python deepcopy of list on assignment

Got this exercise on a python exam. Trying to return a deep o copy of a list like this:

l = list()
l = [0,1,2]
l1 = l
l[0] = 1

l1 should contain [0,1,2] not [1,1,2]

The exercise specified to implement it by using a metaclass.

class deep(type):
    def __new__(meta, classname, bases, classDict):
        return type.__new__(meta, classname, bases, classDict)
    def __init__(cls, name, bases, dct):
        super(deep, cls).__init__(name, bases, dct)
    def __call__(cls, *args, **kwds):
        return type.__call__(cls, *args, **kwds)            
class list(metaclass=deep):
    def __init__(self):
        pass

From what i know , the '=' in python is a statement and not an operator and it can't be overriden. Any idea on how to return a deep copy on assignment? Have been trying quite a lot but with no success.

like image 980
amn Avatar asked Feb 24 '12 15:02

amn


People also ask

How do you Deepcopy a list in Python?

To make a deep copy, use the deepcopy() function of the copy module. In a deep copy, copies are inserted instead of references to objects, so changing one does not change the other.

Does assignment copy list in Python?

So when you create a new variable and assign a list object to it, you are introducing a new reference label to the original object. To recap, the assignment operator (=) creates a new reference to an object in memory. It does not copy anything. This applies to lists as well as any other object in Python.

Does list () create a deep copy?

You don't make a deep copy using list() . (Both list(...) and testList[:] are shallow copies.) You use copy. deepcopy(...) for deep copying a list.

What is Deepcopy () in Python?

What is Deep copy in Python? A deep copy creates a new compound object before inserting copies of the items found in the original into it in a recursive manner. It means first constructing a new collection object and then recursively populating it with copies of the child objects found in the original.


2 Answers

As far as I'm aware, this is not possible in python without using some kind of extra syntax. As you said, you can't override =.

like image 193
Daenyth Avatar answered Oct 05 '22 11:10

Daenyth


To understand what l1 = l does in Python read Other languages have "variables", Python has "names".

To change what l[0] = 1 does you could override l's __setitem__() method:

>>> class L(list):
...     def __setitem__(self, i, v):
...         list.__setitem__(self, i, 10)
... 
>>> l = L()
>>> l.append(1)
>>> l
[1]
>>> l[0] = 0
>>> l
[10]

To change what l = List(); l = [0,1,2] does you could define List.__del__() method in CPython and manipulate the namespace l belongs to e.g., using inspect module. Needless to say you should never do that.

>>> import inspect
>>> class L:
...     def __del__(self):
...         inspect.currentframe().f_globals['l'] = [1,2,3]
... 
>>> l = L()
>>> l = [0]
>>> l
[1, 2, 3]
like image 37
jfs Avatar answered Oct 05 '22 13:10

jfs