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.
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.
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.
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 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.
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 =
.
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With