Search code examples
pythonobjectlanguage-designinstantiation

Does Python copy value or reference upon object instantiation?


A simple question, perhaps, but I can't quite phrase my Google query to find the answer here. I've had the habit of making copies of objects when I pass them into object constructors, like so:

...
def __init__(self, name):
    self._name = name[:]
...

However, when I ran the following test code, it appears to not be necessary, that Python is making deep copies of the object values upon object instantiation:

>>> class Candy(object):
...     def __init__(self, flavor):
...             self.flavor = flavor
...
>>> flav = "cherry"
>>> a = Candy(flav)
>>> a
<__main__.Candy object at 0x00CA4670>
>>> a.flavor
'cherry'
>>> flav += ' and grape'
>>> flav
'cherry and grape'
>>> a.flavor
'cherry'

So, what's the real story here? Thanks!

EDIT:

Thanks to @Olivier for his great answer. The following code documents a better example that Python does copy by reference:

>>> flav = ['a','b']
>>> a = Candy(flav)
>>> a.flavor
['a', 'b']
>>> flav[1] = 'c'
>>> flav
['a', 'c']
>>> a.flavor
['a', 'c']

Solution

  • It is because strings are immutable.

    The operator +=, rather confusingly, actually reassigns the variable it is applied to, if the object is immutable:

    s = 'a'
    ids = id(s)
    s += 'b'
    ids == id(s) # False, because s was reassigned to a new object
    

    So, in your case, in the beginning, both flav and a.flavor point to the same string object:

    flav --------\
                   'cherry'
    a.flavor ----/
    

    But when you write flav += 'and grape' the variable flav gets reassigned to a new string object:

    flav --------> 'cherry and grape'
    a.flavor ----> 'cherry' # <-- that string object never changes
    

    It is confusing, because usually, when you call an operator on a variable, it doesn't change the variable. But just in the case of an immutable object, it does reassign the variable.

    So the final answer to your question is, yes, it makes sense to copy the objects upon instantiation, especially if you are expecting a mutable object (which is often the case). It the object was immutable, it will not harm to copy it anyway.