Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In python, returning an object created in a function body makes a deep copy of it?

I'll try to clarify:

For example, I make a function that locally creates a list, and return it. How does Python create the returned list that exist outside the function body ? Does it use "deepcopy" (or something similar) ?

In [50]: def create_list():
    ...:     sublist1 = [1,2,3]
    ...:     sublist2 = [4,5,6]
    ...:     list_of_lists=[sublist1,sublist1,sublist2]
    ...:     return list_of_lists
    ...: 

In [51]: l=create_list()

In [52]: l
Out[52]: [[1, 2, 3], [1, 2, 3], [4, 5, 6]]

In [53]: l[0].append(4)

In [54]: l
Out[54]: [[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]

Here, the returned list l still contains the sublists. And l[0] and l[1] still reference the same sublist (which is normal Python behavior). So the list and its structure were copied.

And if I call once again create_list() :

In [55]: l2=create_list()

In [56]: l2
Out[56]: [[1, 2, 3], [1, 2, 3], [4, 5, 6]]

In [57]: l
Out[57]: [[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]

A new list l2 has been created, but l is unaffected, which means it does exist outside the function, and its sublists are its own, not references to sublists that would still exist in the function body.

So my question : does Python used deepcopy or something similar to make l ? Not matter what kind of object I return with a function, it will be unaffected by subsequent call to this function ? (as long as the object was created locally in the function)

Do not hesitate to tell me if I'm not clear enough. Thanks,

like image 978
Yann Avatar asked Apr 19 '15 10:04

Yann


1 Answers

When you run the function the second time, the entire function is rerun - it has no memory along the lines of "last time, sublist1 was [1, 2, 3]".

You haven't copied the list [1, 2, 3]. You've created it twice.


Note that if you use a caching decorator like @functools.lru_cache, you'll get surprising results:

>>> @lru_cache()
... def create_list():
...     sublist1 = [1,2,3]
...     sublist2 = [4,5,6]
...     list_of_lists=[sublist1,sublist1,sublist2]
...     return list_of_lists
...
>>> l = create_list(); l
[[1, 2, 3], [1, 2, 3], [4, 5, 6]]
>>> l[0].append(4); l
[[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]
>>> create_list()
[[1, 2, 3, 4], [1, 2, 3, 4], [4, 5, 6]]

Because in this case, python does have a memory of the previous result, and returns the same object

like image 175
Eric Avatar answered Sep 19 '22 05:09

Eric