I was messing around while trying to figure out shallow and deep copying in Python, and noticed that while the identities of a copied set, list, or seemingly any mutable type aren't the same:
In[2]: x1 = {1,2,3}
In[3]: x2 = x1.copy()
In[4]: x1 is x2
Out[4]: False
For immutable types this isn't the case - it looks like a copy points to the same address in memory.
In[6]: f1 = frozenset({1,2,3})
In[7]: f2 = f1.copy()
In[8]: f1 is f2
Out[8]: True
This sort of intuitively makes sense to me - why would you need two identical immutable objects in memory anyways. But I've never seen it before - is there a name for this process? Is it done for speed purposes?
Furthermore, are there any implications of this "not actual copying"? I'm not convinced there are but I want to be sure - the only thing I could come up with is if someone decided to modify mutable types inside an immutable type, which from what I know would be a bad idea anyways.
In[11]: t1 = tuple((1, ['a', 'b']))
In[12]: t2 = tuple(t1) # I would expect an actual copy, but it is not
In[13]: t1[1].append('c')
In[14]: t2
Out[14]: (1, ['a', 'b', 'c'])
We often call lists mutable (meaning they can be changed) and tuples immutable (meaning they cannot be changed).
Python frozenset() Method creates an immutable Set object from an iterable. It is a built-in Python function. As it is a set object therefore we cannot have duplicate values in the frozenset.
Immutability of Tuple Tuples are immutable and hence cannot have any changes in them once they are created in Python. This is because they support the same sequence operations as strings. We all know that strings are immutable. The index operator will select an element from a tuple just like in a string.
Frozen set is just an immutable version of a Python set object. While elements of a set can be modified at any time, elements of the frozen set remain the same after creation. Due to this, frozen sets can be used as keys in Dictionary or as elements of another set.
It's called polymorphism.
Different types can implement the __copy__()
and __deepcopy__()
hooks and do something different that makes sense to their type. The copy
module simply calls those hooks to delegate the actual copy work (or in the case of the set types, you delegate to the set.copy()
method). Immutable types then are free to return self
to avoid wasting memory.
Otherwise, there is no special name for the choice to return self
from __copy__()
for immutable types.
Note that for the tuple-with-list example, you only asked for a shallow copy. Shallow copies of containers always re-use the references to the contents. The same thing would happen with list(some_list_object)
or dict(some_dict_object)
. Use a deep copy instead to ensure that you get a tuple with a copy of the contained list; a new tuple object is then created too:
>>> import copy
>>> t1 = (1, ['a', 'b'])
>>> t2 = copy.deepcopy(t1)
>>> t1 is t2
False
>>> t1[0].append('c')
>>> t2
(1, ['a', 'b'])
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